satellite-env-variables.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013 Magister Solutions Ltd.
4  * Copyright (c) 2018 CNES
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Frans Laakso <frans.laakso@magister.fi>
20  * Author: Mathias Ettinger <mettinger@toulouse.viveris.com>
21  */
22 
24 
25 #include "ns3/boolean.h"
26 #include "ns3/fatal-error.h"
27 #include "ns3/string.h"
28 
29 #include <stdio.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 
34 #ifdef __APPLE__
35 #include <mach-o/dyld.h>
36 #endif
37 
38 NS_LOG_COMPONENT_DEFINE("SatEnvVariables");
39 
40 namespace ns3
41 {
42 
43 NS_OBJECT_ENSURE_REGISTERED(SatEnvVariables);
44 
45 TypeId
47 {
48  static TypeId tid =
49  TypeId("ns3::SatEnvVariables")
50  .SetParent<Object>()
51  .AddConstructor<SatEnvVariables>()
52  .AddAttribute(
53  "CurrentWorkingDirectory",
54  "Current working directory for the simulator.",
55  StringValue(""),
57  MakeStringChecker())
58  .AddAttribute("PathToExecutable",
59  "Path to the simulator executable.",
60  StringValue(""),
62  MakeStringChecker())
63  .AddAttribute("DataPath",
64  "Path to the data folder.",
65  StringValue("contrib/satellite/data"),
66  MakeStringAccessor(&SatEnvVariables::m_dataPath),
67  MakeStringChecker())
68  .AddAttribute("SimulationCampaignName",
69  "Simulation campaign name. Affects the simulation folder.",
70  StringValue(""),
71  MakeStringAccessor(&SatEnvVariables::m_campaignName),
72  MakeStringChecker())
73  .AddAttribute("SimulationTag",
74  "Tag related to the current simulation.",
75  StringValue("default"),
76  MakeStringAccessor(&SatEnvVariables::m_simTag),
77  MakeStringChecker())
78  .AddAttribute("EnableSimulationOutputOverwrite",
79  "Enable simulation output overwrite.",
80  BooleanValue(true),
81  MakeBooleanAccessor(&SatEnvVariables::m_enableOutputOverwrite),
82  MakeBooleanChecker())
83  .AddAttribute("EnableSimInfoOutput",
84  "Enable simulation information output.",
85  BooleanValue(true),
86  MakeBooleanAccessor(&SatEnvVariables::m_enableSimInfoOutput),
87  MakeBooleanChecker())
88  .AddAttribute("EnableSimInfoDiffOutput",
89  "Enable simulation information diff output.",
90  BooleanValue(true),
91  MakeBooleanAccessor(&SatEnvVariables::m_enableSimInfoDiffOutput),
92  MakeBooleanChecker())
93  .AddAttribute("ExcludeSatelliteDataFolderFromSimInfoDiff",
94  "Exclude satellite data folder from the revision diff.",
95  BooleanValue(true),
97  MakeBooleanChecker());
98  return tid;
99 }
100 
101 TypeId
103 {
104  return GetTypeId();
105 }
106 
108  : m_currentWorkingDirectory(""),
109  m_pathToExecutable(""),
110  m_currentWorkingDirectoryFromAttribute(""),
111  m_pathToExecutableFromAttribute(""),
112  m_levelsToCheck(10),
113  m_dataPath("contrib/satellite/data"),
114  m_outputPath(""),
115  m_campaignName(""),
116  m_simRootPath("contrib/satellite/data/sims"),
117  m_simTag("default"),
118  m_enableOutputOverwrite(true),
119  m_isOutputPathInitialized(false),
120  m_enableSimInfoOutput(true),
121  m_enableSimInfoDiffOutput(true),
122  m_excludeDataFolderFromDiff(true),
123  m_isInitialized(false)
124 {
125  NS_LOG_FUNCTION(this);
126 
127  // Attributes are needed already in construction phase:
128  // - ConstructSelf call in constructor
129  // - GetInstanceTypeId needs to be implemented
130  ObjectBase::ConstructSelf(AttributeConstructionList());
131 
132  Initialize();
133 }
134 
135 void
137 {
138  NS_LOG_FUNCTION(this);
139 
140  if (!m_isInitialized)
141  {
142  char currentWorkingDirectory[FILENAME_MAX] = "";
143 
144  if (!getcwd(currentWorkingDirectory, sizeof(currentWorkingDirectory)))
145  {
146  NS_FATAL_ERROR("SatEnvVariables::SatEnvVariables - Could not determine current working "
147  "directory.");
148  }
149  currentWorkingDirectory[sizeof(currentWorkingDirectory) - 1] = '\0';
150  m_currentWorkingDirectory = std::string(currentWorkingDirectory);
151 
152  char pathToExecutable[FILENAME_MAX] = "";
153 
154  int res;
155 #ifdef __linux__
156  res = readlink("/proc/self/exe", pathToExecutable, sizeof(pathToExecutable));
157 #elif __APPLE__
158  uint32_t size = sizeof(pathToExecutable);
159  res = _NSGetExecutablePath(pathToExecutable, &size);
160 #else
161  NS_FATAL_ERROR("SatEnvVariables::SatEnvVariables - Unknown compiler.");
162 #endif
163  if (res < 0)
164  {
165  NS_FATAL_ERROR(
166  "SatEnvVariables::SatEnvVariables - Could not determine the path to executable.");
167  }
168  pathToExecutable[sizeof(pathToExecutable) - 1] = '\0';
169  m_pathToExecutable = std::string(pathToExecutable);
170 
172  {
174  {
176  }
177 
179  }
180 
181  m_isInitialized = true;
182  }
183 }
184 
185 void
187 {
188  NS_LOG_FUNCTION(this);
189 
190  if (m_isInitialized)
191  {
193  m_pathToExecutable = "";
195  m_isInitialized = false;
196  }
197 }
198 
199 void
200 SatEnvVariables::SetCurrentWorkingDirectory(std::string currentWorkingDirectory)
201 {
202  NS_LOG_FUNCTION(this);
203 
204  m_currentWorkingDirectory = currentWorkingDirectory;
205 }
206 
207 void
208 SatEnvVariables::SetPathToExecutable(std::string pathToExecutable)
209 {
210  NS_LOG_FUNCTION(this);
211 
212  m_pathToExecutable = pathToExecutable;
213 }
214 
215 std::string
217 {
218  NS_LOG_FUNCTION(this);
219 
221  {
223  }
224 
225  return m_outputPath;
226 }
227 
228 void
229 SatEnvVariables::SetOutputPath(std::string outputPath)
230 {
231  NS_ASSERT_MSG(IsValidDirectory(outputPath), outputPath << " is not a valid directory");
232  m_outputPath = outputPath;
234 }
235 
236 void
237 SatEnvVariables::SetOutputVariables(std::string campaignName,
238  std::string simTag,
239  bool enableOutputOverwrite)
240 {
241  NS_LOG_FUNCTION(this);
242 
243  m_campaignName = campaignName;
244  m_simTag = simTag;
245  m_enableOutputOverwrite = enableOutputOverwrite;
246 
248 }
249 
251 {
252  NS_LOG_FUNCTION(this);
253 
254  Dispose();
255 }
256 
257 std::string
259 {
260  NS_LOG_FUNCTION(this);
261 
262  NS_LOG_INFO("Current working directory: " << m_currentWorkingDirectory);
263  NS_LOG_INFO(
264  "Current working directory (attribute): " << m_currentWorkingDirectoryFromAttribute);
265 
267  {
268  NS_LOG_INFO("Attribute string is empty, using detected working directory");
270  }
271  else
272  {
273  NS_LOG_INFO("Using attributed working directory");
275  }
276 }
277 
278 std::string
280 {
281  NS_LOG_FUNCTION(this);
282 
283  NS_LOG_INFO("Path to executable: " << m_pathToExecutable);
284  NS_LOG_INFO("Path to executable (attribute): " << m_pathToExecutableFromAttribute);
285 
287  {
288  NS_LOG_INFO("Attribute string is empty, using detected path to executable");
289  return m_pathToExecutable;
290  }
291  else
292  {
293  NS_LOG_INFO("Using attributed path to executable");
295  }
296 }
297 
298 bool
300 {
301  NS_LOG_FUNCTION(this);
302 
303  struct stat st;
304  bool validDirectory = false;
305 
306  if (stat(path.c_str(), &st) == 0)
307  {
308  if (S_ISDIR(st.st_mode))
309  {
310  validDirectory = true;
311  }
312  }
313 
314  NS_LOG_INFO("" << path << " validity: " << validDirectory);
315 
316  return validDirectory;
317 }
318 
319 bool
320 SatEnvVariables::IsValidFile(std::string pathToFile)
321 {
322  NS_LOG_FUNCTION(this);
323 
324  struct stat st;
325  bool validFile = (stat(pathToFile.c_str(), &st) == 0);
326 
327  NS_LOG_INFO("" << pathToFile << " validity: " << validFile);
328 
329  return validFile;
330 }
331 
332 std::string
334 {
335  NS_LOG_FUNCTION(this);
336 
337  return LocateDirectory(GetDataPath());
338 }
339 
340 std::string
341 SatEnvVariables::LocateDirectory(std::string initialPath)
342 {
343  NS_LOG_FUNCTION(this);
344 
345  std::string path;
346  bool directoryFound = false;
347 
348  NS_LOG_INFO("Initial path " << initialPath);
349 
350  for (uint32_t i = 0; i < m_levelsToCheck; i++)
351  {
352  std::stringstream dataPath;
353 
354  for (uint32_t j = 0; j < i; j++)
355  {
356  dataPath << "../";
357  }
358 
359  dataPath << initialPath;
360 
361  NS_LOG_INFO("Checking " << dataPath.str());
362 
363  if (IsValidDirectory(dataPath.str()))
364  {
365  NS_LOG_INFO("Data directory located in " << dataPath.str());
366  path = dataPath.str();
367  directoryFound = true;
368  break;
369  }
370  }
371 
372  if (!directoryFound)
373  {
374  NS_FATAL_ERROR("SatEnvVariables::LocateDirectory - Directory not found within "
375  << m_levelsToCheck << " levels: " << initialPath);
376  }
377 
378  return path;
379 }
380 
381 std::string
382 SatEnvVariables::LocateFile(std::string initialPath)
383 {
384  NS_LOG_FUNCTION(this);
385 
386  std::string path;
387  bool fileFound = false;
388 
389  NS_LOG_INFO("Initial path " << initialPath);
390 
391  for (uint32_t i = 0; i < m_levelsToCheck; i++)
392  {
393  std::stringstream dataPath;
394 
395  for (uint32_t j = 0; j < i; j++)
396  {
397  dataPath << "../";
398  }
399 
400  dataPath << initialPath;
401 
402  NS_LOG_INFO("Checking " << dataPath.str());
403 
404  if (IsValidFile(dataPath.str()))
405  {
406  NS_LOG_INFO("Data directory located in " << dataPath.str());
407  path = dataPath.str();
408  fileFound = true;
409  break;
410  }
411  }
412 
413  if (!fileFound)
414  {
415  NS_FATAL_ERROR("SatEnvVariables::LocateFile - File not found within "
416  << m_levelsToCheck << " levels: " << initialPath);
417  }
418 
419  return path;
420 }
421 
422 std::string
424  std::string simTag,
425  bool enableOutputOverwrite)
426 {
427  NS_LOG_FUNCTION(this);
428 
429  NS_LOG_INFO("Creating output directory");
430 
431  uint32_t safety = 0;
432  std::string safetyTag = "";
433  std::string outputPath = "";
434  bool directoryExists = false;
435  std::string simRootPath = LocateDirectory(m_simRootPath);
436 
437  // If we have set a campaign name
438  if (!campaignName.empty())
439  {
440  std::string tempString = AddToPath(simRootPath, campaignName);
441 
442  // If the campaign name directory does not exist, create it
443  if (!IsValidDirectory(tempString))
444  {
445  CreateDirectory(tempString);
446  }
447  }
448 
449  // As long as the full output folder is created.
450  // Start with false.
451  while (!directoryExists)
452  {
453  outputPath = FormOutputPath(simRootPath, campaignName, simTag, safetyTag);
454 
455  // Create new simulation folder or overwrite
456  if ((!IsValidDirectory(outputPath) && !enableOutputOverwrite) || enableOutputOverwrite)
457  {
458  CreateDirectory(outputPath);
459  directoryExists = true;
460  }
461  // Do not overwrite, but add a new safety string tag to simulation folder
462  else
463  {
464  safety++;
465 
466  NS_LOG_INFO("Directory " << outputPath << " exists, increasing safety number to "
467  << safety);
468 
469  std::stringstream ss;
470  ss << safety;
471  safetyTag = ss.str();
472 
473  // Continue loop and try to create a new directory
474  directoryExists = false;
475  }
476  }
477 
479  m_outputPath = outputPath;
480  return outputPath;
481 }
482 
483 std::string
484 SatEnvVariables::FormOutputPath(std::string simRootPath,
485  std::string campaignName,
486  std::string simTag,
487  std::string safetyTag)
488 {
489  NS_LOG_FUNCTION(this);
490 
491  std::string outputPath = "";
492  std::stringstream tempTag;
493 
494  tempTag << simTag;
495 
496  if (!safetyTag.empty())
497  {
498  tempTag << safetyTag;
499  }
500 
501  outputPath = AddToPath(outputPath, simRootPath);
502  outputPath = AddToPath(outputPath, campaignName);
503  outputPath = AddToPath(outputPath, tempTag.str());
504 
505  NS_LOG_INFO("Formed path " + outputPath);
506 
507  return outputPath;
508 }
509 
510 std::string
511 SatEnvVariables::AddToPath(std::string path, std::string stringToAdd)
512 {
513  NS_LOG_FUNCTION(this);
514 
515  std::stringstream tempPath;
516  tempPath << path;
517 
518  if (!stringToAdd.empty())
519  {
520  if (tempPath.str().empty())
521  {
522  tempPath << stringToAdd;
523  }
524  else
525  {
526  tempPath << "/" << stringToAdd;
527  }
528  }
529  return tempPath.str();
530 }
531 
532 void
534 {
535  NS_LOG_FUNCTION(this);
536 
537  NS_LOG_INFO("Creating directory " + path);
538 
539  mkdir(path.c_str(), 0777);
540 }
541 
542 std::string
544 {
545  NS_LOG_FUNCTION(this);
546 
547  time_t rawtime;
548  struct tm* timeinfo;
549  char buffer[80];
550 
551  time(&rawtime);
552  timeinfo = localtime(&rawtime);
553 
554  strftime(buffer, 80, "%d-%m-%Y %I:%M:%S", timeinfo);
555  std::string str(buffer);
556 
557  NS_LOG_INFO("Date is " << str);
558 
559  return str;
560 }
561 
562 void
564  std::string command,
565  Ptr<SatOutputFileStreamStringContainer> outputContainer)
566 {
567  NS_LOG_FUNCTION(this);
568 
569  FILE* pipe = popen(command.c_str(), "r");
570  if (pipe)
571  {
572  std::string data = "";
573  char buffer[1024];
574  while (!feof(pipe))
575  {
576  if (fgets(buffer, 1024, pipe) != NULL)
577  {
578  buffer[strlen(buffer) - 1] = '\0';
579  data.append(buffer);
580  outputContainer->AddToContainer(data);
581  data = "";
582  }
583  }
584  pclose(pipe);
585  }
586 }
587 
588 void
590 {
591  NS_LOG_FUNCTION(this);
592 
593  std::string dataPath = LocateDirectory(m_outputPath);
594 
595  std::ostringstream fileName;
596  fileName << dataPath << "/SimInfo.log";
597  Ptr<SatOutputFileStreamStringContainer> outputContainer =
598  CreateObject<SatOutputFileStreamStringContainer>(fileName.str().c_str(), std::ios::out);
599 
600  std::ostringstream revisionCommand;
601  revisionCommand << "cd contrib/satellite"
602  << " && git log -1 2>&1";
603  ExecuteCommandAndReadOutput(revisionCommand.str(), outputContainer);
604 
605  std::stringstream line1;
606  line1 << "\nSimulation finished at " << GetCurrentDateAndTime();
607 
608  outputContainer->AddToContainer(line1.str());
609 
610  outputContainer->WriteContainerToFile();
611 
613  {
614  DumpRevisionDiff(dataPath);
615  }
616 }
617 
618 void
620 {
621  NS_LOG_FUNCTION(this);
622 
623  std::ostringstream fileName;
624  fileName << dataPath << "/SimDiff.log";
625  Ptr<SatOutputFileStreamStringContainer> outputContainer =
626  CreateObject<SatOutputFileStreamStringContainer>(fileName.str().c_str(), std::ios::out);
627 
628  std::ostringstream diffCommand;
629  diffCommand << "cd contrib/satellite"
630  << " && git diff"
631  << " --ignore-all-space"
632  << " --ignore-space-change"
633  << " --ignore-blank-lines";
634 
636  {
637  // Requires git 1.9 to work
638  diffCommand << " \":(exclude)" << m_dataPath << "\" ";
639  }
640 
641  diffCommand << " 2>&1";
642 
643  ExecuteCommandAndReadOutput(diffCommand.str(), outputContainer);
644 
645  outputContainer->WriteContainerToFile();
646 }
647 
648 } // namespace ns3
uint32_t m_levelsToCheck
How many directory levels to check for data path.
std::string InitializeOutputFolders(std::string campaignName, std::string simTag, bool enableOutputOverwrite)
Function for forming the output path and directory structure.
void DumpRevisionDiff(std::string dataPath)
void DoInitialize()
Initialize class NOTICE: this function is meant to me used only in test cases, where issues with sing...
bool m_isInitialized
Flag for disposing and initializing.
std::string LocateFile(std::string initialPath)
Function for locating a specific file within the NS-3 simulator folder.
std::string GetPathToExecutable()
Function for getting the path to executable.
bool m_enableOutputOverwrite
Enable simulation output overwrite.
bool IsValidFile(std::string pathToFile)
Function for checking if the file exists.
std::string GetOutputPath()
Function for getting the simulation folder.
void CreateDirectory(std::string path)
Function for creating a directory.
void DumpSimulationInformation()
Function for outputting the most essential simulation specific environmental information.
std::string FormOutputPath(std::string simRootPath, std::string campaignName, std::string simTag, std::string safetyTag)
Function for forming the output path.
void SetOutputVariables(std::string campaignName, std::string simTag, bool enableOutputOverwrite)
Function for setting the output variables.
void SetCurrentWorkingDirectory(std::string currentWorkingDirectory)
Function for setting the path to current working directory.
bool m_excludeDataFolderFromDiff
Is data folder excluded from the simulation information diff.
std::string AddToPath(std::string path, std::string stringToAdd)
Function for forming the next level of a path.
std::string m_simRootPath
Path to the simulation output root folder.
std::string m_currentWorkingDirectoryFromAttribute
Path to current working directory (attribute value)
std::string m_pathToExecutable
Path to executable.
std::string GetCurrentWorkingDirectory()
Function for getting the path to current working directory.
void SetPathToExecutable(std::string pathToExecutable)
Function for setting the path to executable.
virtual TypeId GetInstanceTypeId(void) const
Get the type ID of instance.
std::string LocateDataDirectory()
Function for locating the data directory within the NS-3 simulator folder.
std::string m_dataPath
Default data path.
bool IsValidDirectory(std::string path)
Function for checking if the directory exists.
bool m_enableSimInfoOutput
Is simulation information output enabled.
bool m_enableSimInfoDiffOutput
Is simulation information diff output enabled.
std::string GetDataPath()
Function for locating the data folder.
std::string m_campaignName
Simulation campaign name.
void SetOutputPath(std::string outputPath)
Method for setting the simulation output path.
bool m_isOutputPathInitialized
Is output path initialized.
std::string m_pathToExecutableFromAttribute
Path to executable (attribute value)
std::string LocateDirectory(std::string initialPath)
Function for locating a specific directory within the NS-3 simulator folder.
std::string GetCurrentDateAndTime()
Returns current real world date and time.
void ExecuteCommandAndReadOutput(std::string command, Ptr< SatOutputFileStreamStringContainer > outputContainer)
Function for executing the command and inserting the output into a string container.
std::string m_simTag
Tag related to the current simulation.
void DoDispose()
Reset class NOTICE: this function is meant to me used only in test cases, where issues with singleton...
std::string m_outputPath
Result output path.
static TypeId GetTypeId(void)
NS-3 function for type id.
std::string m_currentWorkingDirectory
Path to current working directory.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.