Loading...
Searching...
No Matches
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
38NS_LOG_COMPONENT_DEFINE("SatEnvVariables");
39
40namespace ns3
41{
42
43NS_OBJECT_ENSURE_REGISTERED(SatEnvVariables);
44
45Ptr<SatEnvVariables> SatEnvVariables::m_instance = nullptr;
46
47TypeId
49{
50 static TypeId tid =
51 TypeId("ns3::SatEnvVariables")
52 .SetParent<Object>()
53 .AddConstructor<SatEnvVariables>()
54 .AddAttribute(
55 "CurrentWorkingDirectory",
56 "Current working directory for the simulator.",
57 StringValue(""),
59 MakeStringChecker())
60 .AddAttribute("PathToExecutable",
61 "Path to the simulator executable.",
62 StringValue(""),
64 MakeStringChecker())
65 .AddAttribute("DataPath",
66 "Path to the data folder.",
67 StringValue("contrib/satellite/data"),
68 MakeStringAccessor(&SatEnvVariables::m_dataPath),
69 MakeStringChecker())
70 .AddAttribute("SimulationCampaignName",
71 "Simulation campaign name. Affects the simulation folder.",
72 StringValue(""),
73 MakeStringAccessor(&SatEnvVariables::m_campaignName),
74 MakeStringChecker())
75 .AddAttribute("SimulationTag",
76 "Tag related to the current simulation.",
77 StringValue("default"),
78 MakeStringAccessor(&SatEnvVariables::m_simTag),
79 MakeStringChecker())
80 .AddAttribute("EnableSimulationOutputOverwrite",
81 "Enable simulation output overwrite.",
82 BooleanValue(true),
83 MakeBooleanAccessor(&SatEnvVariables::m_enableOutputOverwrite),
84 MakeBooleanChecker())
85 .AddAttribute("EnableSimInfoOutput",
86 "Enable simulation information output.",
87 BooleanValue(true),
88 MakeBooleanAccessor(&SatEnvVariables::m_enableSimInfoOutput),
89 MakeBooleanChecker())
90 .AddAttribute("EnableSimInfoDiffOutput",
91 "Enable simulation information diff output.",
92 BooleanValue(true),
94 MakeBooleanChecker())
95 .AddAttribute("ExcludeSatelliteDataFolderFromSimInfoDiff",
96 "Exclude satellite data folder from the revision diff.",
97 BooleanValue(true),
99 MakeBooleanChecker());
100 return tid;
101}
102
108 m_levelsToCheck(10),
109 m_dataPath("contrib/satellite/data"),
110 m_outputPath(""),
111 m_campaignName(""),
112 m_simRootPath("contrib/satellite/data/sims"),
113 m_simTag("default"),
119 m_isInitialized(false)
120{
121 NS_LOG_FUNCTION(this);
122}
123
124void
126{
127 NS_LOG_FUNCTION(this);
128
129 Object::NotifyConstructionCompleted();
130
131 Initialize();
132}
133
134Ptr<SatEnvVariables>
136{
137 if (m_instance == nullptr)
138 {
139 m_instance = CreateObject<SatEnvVariables>();
140 }
141 return m_instance;
142}
143
144void
146{
147 NS_LOG_FUNCTION(this);
148
149 if (!m_isInitialized)
150 {
151 char currentWorkingDirectory[FILENAME_MAX] = "";
152
153 if (!getcwd(currentWorkingDirectory, sizeof(currentWorkingDirectory)))
154 {
155 NS_FATAL_ERROR("SatEnvVariables::SatEnvVariables - Could not determine current working "
156 "directory.");
157 }
158 currentWorkingDirectory[sizeof(currentWorkingDirectory) - 1] = '\0';
159 m_currentWorkingDirectory = std::string(currentWorkingDirectory);
160
161 char pathToExecutable[FILENAME_MAX] = "";
162
163 int res;
164#ifdef __linux__
165 res = readlink("/proc/self/exe", pathToExecutable, sizeof(pathToExecutable));
166#elif __APPLE__
167 uint32_t size = sizeof(pathToExecutable);
168 res = _NSGetExecutablePath(pathToExecutable, &size);
169#else
170 NS_FATAL_ERROR("SatEnvVariables::SatEnvVariables - Unknown compiler.");
171#endif
172 if (res < 0)
173 {
174 NS_FATAL_ERROR(
175 "SatEnvVariables::SatEnvVariables - Could not determine the path to executable.");
176 }
177 pathToExecutable[sizeof(pathToExecutable) - 1] = '\0';
178 m_pathToExecutable = std::string(pathToExecutable);
179
180 if (!IsValidDirectory(LocateDataDirectory() + "/additional-input"))
181 {
182 NS_FATAL_ERROR("No directory additional-input inside "
184 << ". Make sure you executed 'git submodule update --init --recursive' "
185 "from satellite repository");
186 }
187 if (!IsValidDirectory(LocateDataDirectory() + "/scenarios"))
188 {
189 NS_FATAL_ERROR("No directory scenarios inside "
191 << ". Make sure you executed 'git submodule update --init --recursive' "
192 "from satellite repository");
193 }
194 if (!IsValidDirectory(LocateDataDirectory() + "/sgp4"))
195 {
196 NS_FATAL_ERROR("No directory sgp4 inside "
198 << ". Make sure you executed 'git submodule update --init --recursive' "
199 "from satellite repository");
200 }
201
203 {
205 {
207 }
208
210 }
211
212 m_isInitialized = true;
213 }
214}
215
216void
218{
219 NS_LOG_FUNCTION(this);
220
221 if (m_isInitialized)
222 {
226 m_isInitialized = false;
227 }
228}
229
230void
231SatEnvVariables::SetCurrentWorkingDirectory(std::string currentWorkingDirectory)
232{
233 NS_LOG_FUNCTION(this);
234
235 m_currentWorkingDirectory = currentWorkingDirectory;
236}
237
238void
239SatEnvVariables::SetPathToExecutable(std::string pathToExecutable)
240{
241 NS_LOG_FUNCTION(this);
242
243 m_pathToExecutable = pathToExecutable;
244}
245
246std::string
248{
249 NS_LOG_FUNCTION(this);
250
252 {
254 }
255
256 return m_outputPath;
257}
258
259void
260SatEnvVariables::SetOutputPath(std::string outputPath)
261{
262 NS_ASSERT_MSG(IsValidDirectory(outputPath), outputPath << " is not a valid directory");
263 m_outputPath = outputPath;
265}
266
267void
268SatEnvVariables::SetOutputVariables(std::string campaignName,
269 std::string simTag,
270 bool enableOutputOverwrite)
271{
272 NS_LOG_FUNCTION(this);
273
274 m_campaignName = campaignName;
275 m_simTag = simTag;
276 m_enableOutputOverwrite = enableOutputOverwrite;
277
279}
280
282{
283 NS_LOG_FUNCTION(this);
284
285 Dispose();
286}
287
288std::string
290{
291 NS_LOG_FUNCTION(this);
292
293 NS_LOG_INFO("Current working directory: " << m_currentWorkingDirectory);
294 NS_LOG_INFO(
295 "Current working directory (attribute): " << m_currentWorkingDirectoryFromAttribute);
296
298 {
299 NS_LOG_INFO("Attribute string is empty, using detected working directory");
301 }
302 else
303 {
304 NS_LOG_INFO("Using attributed working directory");
306 }
307}
308
309std::string
311{
312 NS_LOG_FUNCTION(this);
313
314 NS_LOG_INFO("Path to executable: " << m_pathToExecutable);
315 NS_LOG_INFO("Path to executable (attribute): " << m_pathToExecutableFromAttribute);
316
318 {
319 NS_LOG_INFO("Attribute string is empty, using detected path to executable");
320 return m_pathToExecutable;
321 }
322 else
323 {
324 NS_LOG_INFO("Using attributed path to executable");
326 }
327}
328
329bool
331{
332 NS_LOG_FUNCTION(this);
333
334 struct stat st;
335 bool validDirectory = false;
336
337 if (stat(path.c_str(), &st) == 0)
338 {
339 if (S_ISDIR(st.st_mode))
340 {
341 validDirectory = true;
342 }
343 }
344
345 NS_LOG_INFO("" << path << " validity: " << validDirectory);
346
347 return validDirectory;
348}
349
350bool
351SatEnvVariables::IsValidFile(std::string pathToFile)
352{
353 NS_LOG_FUNCTION(this);
354
355 struct stat st;
356 bool validFile = (stat(pathToFile.c_str(), &st) == 0);
357
358 NS_LOG_INFO("" << pathToFile << " validity: " << validFile);
359
360 return validFile;
361}
362
363std::string
365{
366 NS_LOG_FUNCTION(this);
367
369}
370
371std::string
372SatEnvVariables::LocateDirectory(std::string initialPath)
373{
374 NS_LOG_FUNCTION(this);
375
376 std::string path;
377 bool directoryFound = false;
378
379 NS_LOG_INFO("Initial path " << initialPath);
380
381 for (uint32_t i = 0; i < m_levelsToCheck; i++)
382 {
383 std::stringstream dataPath;
384
385 for (uint32_t j = 0; j < i; j++)
386 {
387 dataPath << "../";
388 }
389
390 dataPath << initialPath;
391
392 NS_LOG_INFO("Checking " << dataPath.str());
393
394 if (IsValidDirectory(dataPath.str()))
395 {
396 NS_LOG_INFO("Data directory located in " << dataPath.str());
397 path = dataPath.str();
398 directoryFound = true;
399 break;
400 }
401 }
402
403 if (!directoryFound)
404 {
405 NS_FATAL_ERROR("SatEnvVariables::LocateDirectory - Directory not found within "
406 << m_levelsToCheck << " levels: " << initialPath);
407 }
408
409 return path;
410}
411
412std::string
413SatEnvVariables::LocateFile(std::string initialPath)
414{
415 NS_LOG_FUNCTION(this);
416
417 std::string path;
418 bool fileFound = false;
419
420 NS_LOG_INFO("Initial path " << initialPath);
421
422 for (uint32_t i = 0; i < m_levelsToCheck; i++)
423 {
424 std::stringstream dataPath;
425
426 for (uint32_t j = 0; j < i; j++)
427 {
428 dataPath << "../";
429 }
430
431 dataPath << initialPath;
432
433 NS_LOG_INFO("Checking " << dataPath.str());
434
435 if (IsValidFile(dataPath.str()))
436 {
437 NS_LOG_INFO("Data directory located in " << dataPath.str());
438 path = dataPath.str();
439 fileFound = true;
440 break;
441 }
442 }
443
444 if (!fileFound)
445 {
446 NS_FATAL_ERROR("SatEnvVariables::LocateFile - File not found within "
447 << m_levelsToCheck << " levels: " << initialPath);
448 }
449
450 return path;
451}
452
453std::string
455 std::string simTag,
456 bool enableOutputOverwrite)
457{
458 NS_LOG_FUNCTION(this);
459
460 NS_LOG_INFO("Creating output directory");
461
462 uint32_t safety = 0;
463 std::string safetyTag = "";
464 std::string outputPath = "";
465 bool directoryExists = false;
466 std::string simRootPath = LocateDirectory(m_simRootPath);
467
468 // If we have set a campaign name
469 if (!campaignName.empty())
470 {
471 std::string tempString = AddToPath(simRootPath, campaignName);
472
473 // If the campaign name directory does not exist, create it
474 if (!IsValidDirectory(tempString))
475 {
476 CreateDirectory(tempString);
477 }
478 }
479
480 // As long as the full output folder is created.
481 // Start with false.
482 while (!directoryExists)
483 {
484 outputPath = FormOutputPath(simRootPath, campaignName, simTag, safetyTag);
485
486 // Create new simulation folder or overwrite
487 if ((!IsValidDirectory(outputPath) && !enableOutputOverwrite) || enableOutputOverwrite)
488 {
489 CreateDirectory(outputPath);
490 directoryExists = true;
491 }
492 // Do not overwrite, but add a new safety string tag to simulation folder
493 else
494 {
495 safety++;
496
497 NS_LOG_INFO("Directory " << outputPath << " exists, increasing safety number to "
498 << safety);
499
500 std::stringstream ss;
501 ss << safety;
502 safetyTag = ss.str();
503
504 // Continue loop and try to create a new directory
505 directoryExists = false;
506 }
507 }
508
510 m_outputPath = outputPath;
511 return outputPath;
512}
513
514std::string
515SatEnvVariables::FormOutputPath(std::string simRootPath,
516 std::string campaignName,
517 std::string simTag,
518 std::string safetyTag)
519{
520 NS_LOG_FUNCTION(this);
521
522 std::string outputPath = "";
523 std::stringstream tempTag;
524
525 tempTag << simTag;
526
527 if (!safetyTag.empty())
528 {
529 tempTag << safetyTag;
530 }
531
532 outputPath = AddToPath(outputPath, simRootPath);
533 outputPath = AddToPath(outputPath, campaignName);
534 outputPath = AddToPath(outputPath, tempTag.str());
535
536 NS_LOG_INFO("Formed path " + outputPath);
537
538 return outputPath;
539}
540
541std::string
542SatEnvVariables::AddToPath(std::string path, std::string stringToAdd)
543{
544 NS_LOG_FUNCTION(this);
545
546 std::stringstream tempPath;
547 tempPath << path;
548
549 if (!stringToAdd.empty())
550 {
551 if (tempPath.str().empty())
552 {
553 tempPath << stringToAdd;
554 }
555 else
556 {
557 tempPath << "/" << stringToAdd;
558 }
559 }
560 return tempPath.str();
561}
562
563void
565{
566 NS_LOG_FUNCTION(this);
567
568 NS_LOG_INFO("Creating directory " + path);
569
570 mkdir(path.c_str(), 0777);
571}
572
573std::string
575{
576 NS_LOG_FUNCTION(this);
577
578 time_t rawtime;
579 struct tm* timeinfo;
580 char buffer[80];
581
582 time(&rawtime);
583 timeinfo = localtime(&rawtime);
584
585 strftime(buffer, 80, "%d-%m-%Y %I:%M:%S", timeinfo);
586 std::string str(buffer);
587
588 NS_LOG_INFO("Date is " << str);
589
590 return str;
591}
592
593void
595 std::string command,
596 Ptr<SatOutputFileStreamStringContainer> outputContainer)
597{
598 NS_LOG_FUNCTION(this);
599
600 FILE* pipe = popen(command.c_str(), "r");
601 if (pipe)
602 {
603 std::string data = "";
604 char buffer[1024];
605 while (!feof(pipe))
606 {
607 if (fgets(buffer, 1024, pipe) != NULL)
608 {
609 buffer[strlen(buffer) - 1] = '\0';
610 data.append(buffer);
611 outputContainer->AddToContainer(data);
612 data = "";
613 }
614 }
615 pclose(pipe);
616 }
617}
618
619void
621{
622 NS_LOG_FUNCTION(this);
623
624 std::string dataPath = LocateDirectory(m_outputPath);
625
626 std::ostringstream fileName;
627 fileName << dataPath << "/SimInfo.log";
628 Ptr<SatOutputFileStreamStringContainer> outputContainer =
629 CreateObject<SatOutputFileStreamStringContainer>(fileName.str().c_str(), std::ios::out);
630
631 std::ostringstream revisionCommand;
632 revisionCommand << "cd contrib/satellite" << " && git log -1 2>&1";
633 ExecuteCommandAndReadOutput(revisionCommand.str(), outputContainer);
634
635 std::stringstream line1;
636 line1 << "\nSimulation finished at " << GetCurrentDateAndTime();
637
638 outputContainer->AddToContainer(line1.str());
639
640 outputContainer->WriteContainerToFile();
641
643 {
644 DumpRevisionDiff(dataPath);
645 }
646}
647
648void
650{
651 NS_LOG_FUNCTION(this);
652
653 std::ostringstream fileName;
654 fileName << dataPath << "/SimDiff.log";
655 Ptr<SatOutputFileStreamStringContainer> outputContainer =
656 CreateObject<SatOutputFileStreamStringContainer>(fileName.str().c_str(), std::ios::out);
657
658 std::ostringstream diffCommand;
659 diffCommand << "cd contrib/satellite" << " && git diff" << " --ignore-all-space"
660 << " --ignore-space-change" << " --ignore-blank-lines";
661
663 {
664 // Requires git 1.9 to work
665 diffCommand << " \":(exclude)" << m_dataPath << "\" ";
666 }
667
668 diffCommand << " 2>&1";
669
670 ExecuteCommandAndReadOutput(diffCommand.str(), outputContainer);
671
672 outputContainer->WriteContainerToFile();
673}
674
675} // namespace ns3
Class for environmental variables.
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)
static Ptr< SatEnvVariables > GetInstance()
virtual void NotifyConstructionCompleted() override
Notifier called once the ObjectBase is fully constructed.
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.
static Ptr< SatEnvVariables > m_instance
Instance of SatEnvVariables used for singleton template.
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.
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.