PandA-2024.02
fileIO.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2023-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
43 #include "fileIO.hpp"
44 
45 #include "Parameter.hpp"
46 #include "dbgPrintHelper.hpp"
47 #include "exceptions.hpp"
48 #include "file_IO_constants.hpp"
49 #include "string_manipulation.hpp"
50 
51 #include <cstdlib>
52 #include <random>
53 #include <regex>
54 
55 fileIO_istreamRef fileIO_istream_open(const std::string& name)
56 {
57  fileIO_istreamRef res_file;
58  res_file = fileIO_istreamRef(new igzstream((name).c_str()));
59  if(res_file->fail())
60  {
61  res_file = fileIO_istreamRef(new igzstream((name + ".gz").c_str()));
62  if(res_file->fail())
63  {
64  res_file = fileIO_istreamRef(new igzstream((name + ".Z").c_str()));
65  if(res_file->fail())
66  {
67  res_file = fileIO_istreamRef(new std::ifstream(name.c_str()));
68  if(res_file->fail())
69  {
70  THROW_ERROR("Error in opening " + name);
71  }
72  }
73  }
74  }
75  return res_file;
76 }
77 
78 int PandaSystem(const ParameterConstRef Param, const std::string& system_command, bool host_exec,
79  const std::string& output, const unsigned int type, const bool background, const size_t timeout)
80 {
81  static size_t counter = 0;
82  const std::string actual_output = output == "" ? Param->getOption<std::string>(OPT_output_temporary_directory) +
83  STR_CST_file_IO_shell_output_file + "_" + STR(counter) :
84  GetPath(output);
85  const std::string script_file_name = Param->getOption<std::string>(OPT_output_temporary_directory) +
86  STR_CST_file_IO_shell_script + "_" + STR(counter++);
87  counter++;
88  std::ofstream script_file(script_file_name.c_str());
89  script_file << "#!/bin/bash" << std::endl;
90  if(host_exec)
91  {
92  script_file << "if [ ! -z \"$APPDIR\" ]; then\n"
93  << " export PATH=$(sed -E 's/\\/tmp\\/.mount[^\\:]+\\://g' <<< $PATH)\n"
94  << " export LD_LIBRARY_PATH=$(sed -E 's/\\/tmp\\/.mount[^\\:]+\\://g' <<< $LD_LIBRARY_PATH)\n"
95  << " export PERLLIB=$(sed -E 's/\\/tmp\\/.mount[^\\:]+\\://g' <<< $PERLLIB)\n"
96  << "fi\n";
97  }
98  script_file << "ulimit -s 131072" << std::endl;
99  script_file << "cd " << GetCurrentPath() << std::endl;
100  THROW_ASSERT(not background or timeout == 0, "Background and timeout cannot be specified at the same time");
101  if(background)
102  {
103  script_file << "(";
104  }
105  script_file << "(" << system_command << ") ";
106  if(Param->getOption<unsigned int>(OPT_output_level) >= OUTPUT_LEVEL_PEDANTIC)
107  {
108  switch(type)
109  {
110  case(0):
111  {
112  script_file << " > /dev/null 2>&1 ";
113  break;
114  }
115  case(1):
116  {
117  script_file << " 2>/dev/null | tee " << actual_output;
118  break;
119  }
120  case(2):
121  {
122  script_file << " 2>&1 1>/dev/null | tee " << actual_output;
123  break;
124  }
125  case(3):
126  {
127  script_file << " 2>&1 | tee " << actual_output;
128  break;
129  }
130  default:
131  {
132  THROW_UNREACHABLE("Unexpected type of stream selected " + STR(type));
133  }
134  }
135  }
136  else
137  {
138  switch(type)
139  {
140  case(0):
141  {
142  script_file << " > /dev/null 2>&1 ";
143  break;
144  }
145  case(1):
146  {
147  script_file << " 2> /dev/null > " << actual_output;
148  break;
149  }
150  case(2):
151  {
152  script_file << " > /dev/null 2> " << actual_output;
153  break;
154  }
155  case(3):
156  {
157  script_file << " > " << actual_output << " 2>&1 ";
158  break;
159  }
160  default:
161  {
162  THROW_UNREACHABLE("Unexpected type of stream selected " + STR(type));
163  }
164  }
165  }
166  if(background)
167  {
168  script_file << ") &";
169  }
170  script_file << std::endl;
171  if(Param->getOption<unsigned int>(OPT_output_level) >= OUTPUT_LEVEL_PEDANTIC)
172  {
173  script_file << "exit ${PIPESTATUS[0]}" << std::endl;
174  }
175  script_file.close();
176  if(timeout != 0)
177  {
178  const std::string timeout_file_name = Param->getOption<std::string>(OPT_output_temporary_directory) +
179  STR_CST_file_IO_shell_script + "_" + STR(counter++);
180  counter++;
181  std::ofstream timeout_file(timeout_file_name.c_str());
182  timeout_file << "#!/bin/bash" << std::endl;
183  timeout_file << "timeout --foreground " << STR(timeout) << "m bash -f " << script_file_name << std::endl;
184  timeout_file.close();
185  const std::string command = "bash -f " + timeout_file_name + "";
186  return system(command.c_str());
187  }
188  else
189  {
190  const std::string command = "bash -f " + script_file_name + "";
191  return system(command.c_str());
192  }
193 }
194 
195 bool NaturalVersionOrder(const std::filesystem::path& _x, const std::filesystem::path& _y)
196 {
197  const std::regex version_number("\\d+(\\.\\d+)*");
198  const auto x = _x.string(), y = _y.string();
199  std::cmatch mx, my;
200  if(std::regex_search(x.c_str(), mx, version_number))
201  {
202  if(std::regex_search(y.c_str(), my, version_number))
203  {
204  const char *px = mx[0].first, *lx;
205  const char *py = my[0].first, *ly;
206  do
207  {
208  lx = std::find(px, mx[0].second, '.');
209  ly = std::find(py, my[0].second, '.');
210  if(py == ly)
211  {
212  return false;
213  }
214  auto dx = std::distance(px, lx), dy = std::distance(py, ly);
215  if(dx != dy)
216  {
217  return dx < dy;
218  }
219  do
220  {
221  if(*px != *py)
222  {
223  return *px < *py;
224  }
225  ++py;
226  } while(++px != lx);
227  ++py;
228  } while(++px != mx[0].second);
229  return true;
230  }
231  return false;
232  }
233  else if(std::regex_search(_y.string().c_str(), my, version_number))
234  {
235  return true;
236  }
237  return _x < _y;
238 }
239 
240 template <typename T>
241 void array_rand(T* arr, size_t size)
242 {
243  static std::random_device rd;
244  static std::mt19937_64 gen(rd());
245  uint64_t rnd = 0;
246  size_t i;
247 
248  for(i = 0; i < size; ++i, rnd >>= sizeof(T) * 8)
249  {
250  if(i % sizeof(uint64_t) == 0)
251  rnd = gen();
252  arr[i] = static_cast<T>(rnd);
253  }
254 }
255 
256 /*
257  * unique_path was implemented based on the Boost implementation
258  * whose copyright notice is reported below
259  *
260  * (C) Copyright Beman Dawes 2010.
261  * Use, modification and distribution are subject to the
262  * Boost Software License - Version 1.0 - August 17th, 2003
263  *
264  * Permission is hereby granted, free of charge, to any person or organization
265  * obtaining a copy of the software and accompanying documentation covered by
266  * this license (the "Software") to use, reproduce, display, distribute,
267  * execute, and transmit the Software, and to prepare derivative works of the
268  * Software, and to permit third-parties to whom the Software is furnished to
269  * do so, all subject to the following:
270  *
271  * The copyright notices in the Software and this entire statement, including
272  * the above license grant, this restriction and the following disclaimer,
273  * must be included in all copies of the Software, in whole or in part, and
274  * all derivative works of the Software, unless such copies or derivative
275  * works are solely in the form of machine-executable object code generated by
276  * a source language processor.
277  *
278  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
279  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
280  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
281  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
282  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
283  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
284  * DEALINGS IN THE SOFTWARE.
285  */
286 std::filesystem::path unique_path(const std::filesystem::path& model)
287 {
288  // This function used wstring for fear of misidentifying
289  // a part of a multibyte character as a percent sign.
290  // However, double byte encodings only have 80-FF as lead
291  // bytes and 40-7F as trailing bytes, whereas % is 25.
292  // So, use string on POSIX and avoid conversions.
293 
294  std::filesystem::path::string_type s(model.native());
295 
296  const char hex[] = "0123456789abcdef";
297  const char percent = '%';
298 
299  char ran[] = "123456789abcdef"; // init to avoid clang static analyzer message
300  // see ticket #8954
301  const int max_nibbles = 2 * sizeof(ran); // 4-bits per nibble
302 
303  int nibbles_used = max_nibbles;
304  for(std::filesystem::path::string_type::size_type i = 0; i < s.size(); ++i)
305  {
306  if(s[i] == percent) // digit request
307  {
308  if(nibbles_used == max_nibbles)
309  {
310  array_rand(ran, sizeof(ran));
311  nibbles_used = 0;
312  }
313  int c = ran[nibbles_used / 2];
314  c >>= 4 * (nibbles_used++ & 1); // if odd, shift right 1 nibble
315  s[i] = hex[c & 0xf]; // convert to hex digit and replace
316  }
317  }
318 
319  return s;
320 }
File containing functions and utilities to support the printing of debug messagges.
User classes.
Definition: gzstream.hpp:142
bool NaturalVersionOrder(const std::filesystem::path &_x, const std::filesystem::path &_y)
Definition: fileIO.cpp:195
exceptions managed by PandA
volatile int output[DIM_Y][DIM_X]
Definition: los.h:1
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
std::filesystem::path unique_path(const std::filesystem::path &model)
Definition: fileIO.cpp:286
#define ran
Definition: spmv_test.c:4
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
#define STR_CST_file_IO_shell_output_file
The file used to store shell output.
constants used in Input/Output
#define STR_CST_file_IO_shell_script
The file used to store the script shell.
utility function used to read files.
fileIO_istreamRef fileIO_istream_open(const std::string &name)
this function returns an istream compressed or not.
Definition: fileIO.cpp:55
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
void array_rand(T *arr, size_t size)
Definition: fileIO.cpp:241
list command
Definition: test_panda.py:921
int PandaSystem(const ParameterConstRef Param, const std::string &system_command, bool host_exec, const std::string &output, const unsigned int type, const bool background, const size_t timeout)
System call forcing execution with bash.
Definition: fileIO.cpp:78
#define OUTPUT_LEVEL_PEDANTIC
verbose debugging print is performed.
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
TYPE distance(TYPE position_x[nAtoms], TYPE position_y[nAtoms], TYPE position_z[nAtoms], int i, int j)
Definition: md_kernel_test.c:3
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
this class is used to manage the command-line or XML options.
std::string GetCurrentPath()
Definition: fileIO.hpp:123
unsigned counter[N_THREADS]
Definition: data.c:3
x
Return the smallest n such that 2^n >= _x.
refcount< std::istream > fileIO_istreamRef
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:56 for PandA-2024.02 by doxygen 1.8.13