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 
171  if (!IsValidDirectory(LocateDataDirectory() + "/additional-input"))
172  {
173  NS_FATAL_ERROR("No directory additional-input inside "
175  << ". Make sure you executed 'git submodule update --init --recursive' "
176  "from satellite repository");
177  }
178  if (!IsValidDirectory(LocateDataDirectory() + "/scenarios"))
179  {
180  NS_FATAL_ERROR("No directory scenarios inside "
182  << ". Make sure you executed 'git submodule update --init --recursive' "
183  "from satellite repository");
184  }
185  if (!IsValidDirectory(LocateDataDirectory() + "/sgp4"))
186  {
187  NS_FATAL_ERROR("No directory sgp4 inside "
189  << ". Make sure you executed 'git submodule update --init --recursive' "
190  "from satellite repository");
191  }
192 
194  {
196  {
198  }
199 
201  }
202 
203  m_isInitialized = true;
204  }
205 }
206 
207 void
209 {
210  NS_LOG_FUNCTION(this);
211 
212  if (m_isInitialized)
213  {
215  m_pathToExecutable = "";
217  m_isInitialized = false;
218  }
219 }
220 
221 void
222 SatEnvVariables::SetCurrentWorkingDirectory(std::string currentWorkingDirectory)
223 {
224  NS_LOG_FUNCTION(this);
225 
226  m_currentWorkingDirectory = currentWorkingDirectory;
227 }
228 
229 void
230 SatEnvVariables::SetPathToExecutable(std::string pathToExecutable)
231 {
232  NS_LOG_FUNCTION(this);
233 
234  m_pathToExecutable = pathToExecutable;
235 }
236 
237 std::string
239 {
240  NS_LOG_FUNCTION(this);
241 
243  {
245  }
246 
247  return m_outputPath;
248 }
249 
250 void
251 SatEnvVariables::SetOutputPath(std::string outputPath)
252 {
253  NS_ASSERT_MSG(IsValidDirectory(outputPath), outputPath << " is not a valid directory");
254  m_outputPath = outputPath;
256 }
257 
258 void
259 SatEnvVariables::SetOutputVariables(std::string campaignName,
260  std::string simTag,
261  bool enableOutputOverwrite)
262 {
263  NS_LOG_FUNCTION(this);
264 
265  m_campaignName = campaignName;
266  m_simTag = simTag;
267  m_enableOutputOverwrite = enableOutputOverwrite;
268 
270 }
271 
273 {
274  NS_LOG_FUNCTION(this);
275 
276  Dispose();
277 }
278 
279 std::string
281 {
282  NS_LOG_FUNCTION(this);
283 
284  NS_LOG_INFO("Current working directory: " << m_currentWorkingDirectory);
285  NS_LOG_INFO(
286  "Current working directory (attribute): " << m_currentWorkingDirectoryFromAttribute);
287 
289  {
290  NS_LOG_INFO("Attribute string is empty, using detected working directory");
292  }
293  else
294  {
295  NS_LOG_INFO("Using attributed working directory");
297  }
298 }
299 
300 std::string
302 {
303  NS_LOG_FUNCTION(this);
304 
305  NS_LOG_INFO("Path to executable: " << m_pathToExecutable);
306  NS_LOG_INFO("Path to executable (attribute): " << m_pathToExecutableFromAttribute);
307 
309  {
310  NS_LOG_INFO("Attribute string is empty, using detected path to executable");
311  return m_pathToExecutable;
312  }
313  else
314  {
315  NS_LOG_INFO("Using attributed path to executable");
317  }
318 }
319 
320 bool
322 {
323  NS_LOG_FUNCTION(this);
324 
325  struct stat st;
326  bool validDirectory = false;
327 
328  if (stat(path.c_str(), &st) == 0)
329  {
330  if (S_ISDIR(st.st_mode))
331  {
332  validDirectory = true;
333  }
334  }
335 
336  NS_LOG_INFO("" << path << " validity: " << validDirectory);
337 
338  return validDirectory;
339 }
340 
341 bool
342 SatEnvVariables::IsValidFile(std::string pathToFile)
343 {
344  NS_LOG_FUNCTION(this);
345 
346  struct stat st;
347  bool validFile = (stat(pathToFile.c_str(), &st) == 0);
348 
349  NS_LOG_INFO("" << pathToFile << " validity: " << validFile);
350 
351  return validFile;
352 }
353 
354 std::string
356 {
357  NS_LOG_FUNCTION(this);
358 
359  return LocateDirectory(GetDataPath());
360 }
361 
362 std::string
363 SatEnvVariables::LocateDirectory(std::string initialPath)
364 {
365  NS_LOG_FUNCTION(this);
366 
367  std::string path;
368  bool directoryFound = false;
369 
370  NS_LOG_INFO("Initial path " << initialPath);
371 
372  for (uint32_t i = 0; i < m_levelsToCheck; i++)
373  {
374  std::stringstream dataPath;
375 
376  for (uint32_t j = 0; j < i; j++)
377  {
378  dataPath << "../";
379  }
380 
381  dataPath << initialPath;
382 
383  NS_LOG_INFO("Checking " << dataPath.str());
384 
385  if (IsValidDirectory(dataPath.str()))
386  {
387  NS_LOG_INFO("Data directory located in " << dataPath.str());
388  path = dataPath.str();
389  directoryFound = true;
390  break;
391  }
392  }
393 
394  if (!directoryFound)
395  {
396  NS_FATAL_ERROR("SatEnvVariables::LocateDirectory - Directory not found within "
397  << m_levelsToCheck << " levels: " << initialPath);
398  }
399 
400  return path;
401 }
402 
403 std::string
404 SatEnvVariables::LocateFile(std::string initialPath)
405 {
406  NS_LOG_FUNCTION(this);
407 
408  std::string path;
409  bool fileFound = false;
410 
411  NS_LOG_INFO("Initial path " << initialPath);
412 
413  for (uint32_t i = 0; i < m_levelsToCheck; i++)
414  {
415  std::stringstream dataPath;
416 
417  for (uint32_t j = 0; j < i; j++)
418  {
419  dataPath << "../";
420  }
421 
422  dataPath << initialPath;
423 
424  NS_LOG_INFO("Checking " << dataPath.str());
425 
426  if (IsValidFile(dataPath.str()))
427  {
428  NS_LOG_INFO("Data directory located in " << dataPath.str());
429  path = dataPath.str();
430  fileFound = true;
431  break;
432  }
433  }
434 
435  if (!fileFound)
436  {
437  NS_FATAL_ERROR("SatEnvVariables::LocateFile - File not found within "
438  << m_levelsToCheck << " levels: " << initialPath);
439  }
440 
441  return path;
442 }
443 
444 std::string
446  std::string simTag,
447  bool enableOutputOverwrite)
448 {
449  NS_LOG_FUNCTION(this);
450 
451  NS_LOG_INFO("Creating output directory");
452 
453  uint32_t safety = 0;
454  std::string safetyTag = "";
455  std::string outputPath = "";
456  bool directoryExists = false;
457  std::string simRootPath = LocateDirectory(m_simRootPath);
458 
459  // If we have set a campaign name
460  if (!campaignName.empty())
461  {
462  std::string tempString = AddToPath(simRootPath, campaignName);
463 
464  // If the campaign name directory does not exist, create it
465  if (!IsValidDirectory(tempString))
466  {
467  CreateDirectory(tempString);
468  }
469  }
470 
471  // As long as the full output folder is created.
472  // Start with false.
473  while (!directoryExists)
474  {
475  outputPath = FormOutputPath(simRootPath, campaignName, simTag, safetyTag);
476 
477  // Create new simulation folder or overwrite
478  if ((!IsValidDirectory(outputPath) && !enableOutputOverwrite) || enableOutputOverwrite)
479  {
480  CreateDirectory(outputPath);
481  directoryExists = true;
482  }
483  // Do not overwrite, but add a new safety string tag to simulation folder
484  else
485  {
486  safety++;
487 
488  NS_LOG_INFO("Directory " << outputPath << " exists, increasing safety number to "
489  << safety);
490 
491  std::stringstream ss;
492  ss << safety;
493  safetyTag = ss.str();
494 
495  // Continue loop and try to create a new directory
496  directoryExists = false;
497  }
498  }
499 
501  m_outputPath = outputPath;
502  return outputPath;
503 }
504 
505 std::string
506 SatEnvVariables::FormOutputPath(std::string simRootPath,
507  std::string campaignName,
508  std::string simTag,
509  std::string safetyTag)
510 {
511  NS_LOG_FUNCTION(this);
512 
513  std::string outputPath = "";
514  std::stringstream tempTag;
515 
516  tempTag << simTag;
517 
518  if (!safetyTag.empty())
519  {
520  tempTag << safetyTag;
521  }
522 
523  outputPath = AddToPath(outputPath, simRootPath);
524  outputPath = AddToPath(outputPath, campaignName);
525  outputPath = AddToPath(outputPath, tempTag.str());
526 
527  NS_LOG_INFO("Formed path " + outputPath);
528 
529  return outputPath;
530 }
531 
532 std::string
533 SatEnvVariables::AddToPath(std::string path, std::string stringToAdd)
534 {
535  NS_LOG_FUNCTION(this);
536 
537  std::stringstream tempPath;
538  tempPath << path;
539 
540  if (!stringToAdd.empty())
541  {
542  if (tempPath.str().empty())
543  {
544  tempPath << stringToAdd;
545  }
546  else
547  {
548  tempPath << "/" << stringToAdd;
549  }
550  }
551  return tempPath.str();
552 }
553 
554 void
556 {
557  NS_LOG_FUNCTION(this);
558 
559  NS_LOG_INFO("Creating directory " + path);
560 
561  mkdir(path.c_str(), 0777);
562 }
563 
564 std::string
566 {
567  NS_LOG_FUNCTION(this);
568 
569  time_t rawtime;
570  struct tm* timeinfo;
571  char buffer[80];
572 
573  time(&rawtime);
574  timeinfo = localtime(&rawtime);
575 
576  strftime(buffer, 80, "%d-%m-%Y %I:%M:%S", timeinfo);
577  std::string str(buffer);
578 
579  NS_LOG_INFO("Date is " << str);
580 
581  return str;
582 }
583 
584 void
586  std::string command,
587  Ptr<SatOutputFileStreamStringContainer> outputContainer)
588 {
589  NS_LOG_FUNCTION(this);
590 
591  FILE* pipe = popen(command.c_str(), "r");
592  if (pipe)
593  {
594  std::string data = "";
595  char buffer[1024];
596  while (!feof(pipe))
597  {
598  if (fgets(buffer, 1024, pipe) != NULL)
599  {
600  buffer[strlen(buffer) - 1] = '\0';
601  data.append(buffer);
602  outputContainer->AddToContainer(data);
603  data = "";
604  }
605  }
606  pclose(pipe);
607  }
608 }
609 
610 void
612 {
613  NS_LOG_FUNCTION(this);
614 
615  std::string dataPath = LocateDirectory(m_outputPath);
616 
617  std::ostringstream fileName;
618  fileName << dataPath << "/SimInfo.log";
619  Ptr<SatOutputFileStreamStringContainer> outputContainer =
620  CreateObject<SatOutputFileStreamStringContainer>(fileName.str().c_str(), std::ios::out);
621 
622  std::ostringstream revisionCommand;
623  revisionCommand << "cd contrib/satellite"
624  << " && git log -1 2>&1";
625  ExecuteCommandAndReadOutput(revisionCommand.str(), outputContainer);
626 
627  std::stringstream line1;
628  line1 << "\nSimulation finished at " << GetCurrentDateAndTime();
629 
630  outputContainer->AddToContainer(line1.str());
631 
632  outputContainer->WriteContainerToFile();
633 
635  {
636  DumpRevisionDiff(dataPath);
637  }
638 }
639 
640 void
642 {
643  NS_LOG_FUNCTION(this);
644 
645  std::ostringstream fileName;
646  fileName << dataPath << "/SimDiff.log";
647  Ptr<SatOutputFileStreamStringContainer> outputContainer =
648  CreateObject<SatOutputFileStreamStringContainer>(fileName.str().c_str(), std::ios::out);
649 
650  std::ostringstream diffCommand;
651  diffCommand << "cd contrib/satellite"
652  << " && git diff"
653  << " --ignore-all-space"
654  << " --ignore-space-change"
655  << " --ignore-blank-lines";
656 
658  {
659  // Requires git 1.9 to work
660  diffCommand << " \":(exclude)" << m_dataPath << "\" ";
661  }
662 
663  diffCommand << " 2>&1";
664 
665  ExecuteCommandAndReadOutput(diffCommand.str(), outputContainer);
666 
667  outputContainer->WriteContainerToFile();
668 }
669 
670 } // 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.