AliPhysics  63e47e1 (63e47e1)
AliYAMLConfiguration.cxx
Go to the documentation of this file.
1 //
2 //
3 
4 #include "AliYAMLConfiguration.h"
5 
6 #include <cstdio>
7 #include <fstream>
8 
9 #include <TSystem.h>
10 #include <TGrid.h>
11 #include <TFile.h>
12 #include <TUUID.h>
13 
17 
18 namespace PWG {
19 namespace Tools {
20 
27 AliYAMLConfiguration::AliYAMLConfiguration(const std::string prefixString, const std::string delimiterCharacter):
28  TObject(),
29  fConfigurations(),
30  fConfigurationsStrings(),
31  fInitialized(false),
32  fPrefixString(prefixString),
33  fDelimiter(delimiterCharacter)
34 {
35 }
36 
44 int AliYAMLConfiguration::AddEmptyConfiguration(const std::string & configurationName)
45 {
46  YAML::Node node;
47  AliInfoStream() << "Adding configuration \"" << configurationName << "\" as an empty YAML node.\n";
48  return AddConfiguration(node, configurationName);
49 }
50 
59 int AliYAMLConfiguration::AddConfiguration(std::string configurationFilename, std::string configurationName)
60 {
61  SetupReadingConfigurationFilePath(configurationFilename, configurationName);
62 
63  // Add file
64  if (DoesFileExist(configurationFilename) == false) {
65  AliErrorStream() << "Configuration filename \"" << configurationFilename << "\" does not exist!\n";
66  return -1;
67  }
68 
69  // Create node from filename
70  auto node = YAML::LoadFile(configurationFilename);
71 
72  if (node.IsNull() == true) {
73  AliErrorStream() << "The node at configuration filename \"" << configurationFilename << "\" is null and will not be added!\n";
74  return -1;
75  }
76 
77  AliInfoStream() << "Adding configuration \"" << configurationName << "\" located at \"" << configurationFilename << "\".\n";
78  return AddConfiguration(node, configurationName);
79 }
80 
89 int AliYAMLConfiguration::AddConfiguration(const YAML::Node node, std::string configurationName)
90 {
91  if (configurationName == "")
92  {
93  // Attempt to get name from node
94  // It is fine if the node is empty
95  GetPropertyFromNode(node, "name", configurationName);
96  }
97 
98  if (configurationName == "") {
99  AliErrorStream() << "Could not determine a name for the configuration:\n\"\n" << node << "\n\" Configuration will not be added!\n";
100  return -1;
101  }
102 
103  // Add the configuration
104  AliDebugStream(2) << "Adding configuration \"" << configurationName << "\".\n";
105  fConfigurations.push_back(std::make_pair(configurationName, node));
106 
107  // Return the location of the new configuration
108  return fConfigurations.size() - 1;
109 }
110 
119 {
120  bool returnValue = false;
121  if (i < fConfigurations.size())
122  {
123  fConfigurations.erase(fConfigurations.begin() + i);
124  returnValue = true;
125  }
126 
127  return returnValue;
128 }
129 
138 bool AliYAMLConfiguration::WriteConfiguration(const std::string & filename, const unsigned int index) const
139 {
140  // Write to a local temp filename
141  TUUID tempUUID;
142  std::string localFilename = tempUUID.AsString();
143  localFilename += ".yaml";
144 
145  if (!DoesConfigurationExist(index)) {
146  AliWarningStream() << "Requested configuration index " << index << " does not exist - it cannot be written!\n";
147  return false;
148  }
149  auto configPair = fConfigurations.at(index);
150  std::ofstream outputFile(localFilename);
151  outputFile << configPair.second;
152  outputFile.close();
153 
154  // Hanldes writing to places like AliEn
155  WriteConfigurationToFilePath(localFilename, filename);
156 
157  remove(localFilename.c_str());
158 
159  return true;
160 }
161 
170 bool AliYAMLConfiguration::WriteConfiguration(const std::string & filename, const std::string & configurationName) const
171 {
172  return WriteConfiguration(filename, GetConfigurationIndexFromName(configurationName, fConfigurations));
173 }
174 
183 bool AliYAMLConfiguration::CompareConfigurations(const int configIndex1, const int configIndex2) const
184 {
185  bool returnValue = false;
186 
187  bool configsExist = true;
188  std::vector<int> configs = {configIndex1, configIndex2};
189  for (auto config : configs) {
190  if (!DoesConfigurationExist(config)) {
191  AliErrorStream() << "Configuration at index " << config << " does not exist.\n";
192  configsExist = false;
193  }
194  }
195 
196  if (configsExist)
197  {
198  // Generate YAML nodes for the comparison
199  auto configPair1 = GetConfiguration(configIndex1);
200  auto configPair2 = GetConfiguration(configIndex2);
201 
202  // Need to stream the configuration back to a string to remove the comments
203  // since they are not preserved in the YAML node.
204  std::stringstream config1SS;
205  config1SS << configPair1.second;
206  std::stringstream config2SS;
207  config2SS << configPair2.second;
208 
209  // Compare the nodes. Make the comparison as strings, as the YAML nodes do _not_ match,
210  // despite the strings matching. In fact, the YAML nodes will _not_ match even if they
211  // are generated from the same string....
212  if (config1SS.str() == config2SS.str()) {
213  returnValue = true;
214  }
215  else {
216  // Already should be the case, but just to be explicit.
217  returnValue = false;
218 
219  // Inform the user about the details of the mismatch
220  std::stringstream errorMessageSS;
221  errorMessageSS << "Configuration mismatch between configuration at index " << configIndex1 << " and at index " << configIndex2 << "\n";
222  errorMessageSS << "Config 1:\n";
223  Print(errorMessageSS, configIndex1);
224  errorMessageSS << "Config 2:\n";
225  Print(errorMessageSS, configIndex2);
226  AliWarningStream() << errorMessageSS.str();
227  }
228  }
229 
230  return returnValue;
231 }
232 
233 
242 inline bool AliYAMLConfiguration::DoesFileExist(const std::string & filename) const
243 {
244  std::ifstream inFile(filename);
245  return inFile.good();
246 }
247 
256 void AliYAMLConfiguration::SetupReadingConfigurationFilePath(std::string & filename, const std::string & fileIdentifier) const
257 {
258  if (filename != "")
259  {
260  // Handle if in AliPhysics and includes $ALICE_PHYSICS
261  filename = gSystem->ExpandPathName(filename.c_str());
262 
263  // Handle grid
264  if(filename.find("alien://") != std::string::npos)
265  {
266  AliDebug(2, TString::Format("Opening file \"%s\" on the grid!", filename.c_str()));
267  // Initialize AliEn connection if needed
268  if (!gGrid) {
269  TGrid::Connect("alien://");
270  }
271 
272  // Determine the local filename and copy file to local directory
273  std::string localFilename = gSystem->BaseName(filename.c_str());
274  // Add identifier if it's not an empty string
275  if (fileIdentifier != "") {
276  localFilename = fileIdentifier + "." + localFilename;
277  }
278  // Add UUID to ensure there are no conflicts if multiple yaml configs have the same configuration file name
279  TUUID tempUUID;
280  localFilename = "." + localFilename;
281  localFilename = tempUUID.AsString() + localFilename;
282 
283  // Copy file
284  TFile::Cp(filename.c_str(), localFilename.c_str());
285 
286  // yaml-cpp should only open the local file
287  filename = localFilename;
288  }
289  }
290 }
291 
299 void AliYAMLConfiguration::WriteConfigurationToFilePath(const std::string & localFilename, std::string filename) const
300 {
301  bool cannotWriteFile = false;
302  if (localFilename == "") {
303  AliErrorStream() << "Local filename is null, so the file cannot be written!\n";
304  cannotWriteFile = true;
305  }
306  if (filename == "") {
307  AliErrorStream() << "Filename is null, so the file cannot be written\n";
308  cannotWriteFile = true;
309  }
310 
311  if (cannotWriteFile == false) {
312  // Handle if in AliPhysics and includes $ALICE_PHYSICS
313  filename = gSystem->ExpandPathName(filename.c_str());
314 
315  // Handle grid
316  if(filename.find("alien://") != std::string::npos)
317  {
318  AliDebugStream(2) << "Writing file \"" << filename << "\" on the grid!\n";
319  // Initialize AliEn connection if needed
320  if (!gGrid) {
321  TGrid::Connect("alien://");
322  }
323  }
324 
325  // Copy file
326  AliDebugStream(2) << "Copying localFilename \"" << localFilename << "\" to filename \"" << filename << "\".\n";
327  TFile::Cp(localFilename.c_str(), filename.c_str());
328  }
329 }
330 
341 {
342  // Copy all configurations to their respective strings.
343  // That way, the strings will be successfully streamed by ROOT and the YAML nodes can be re-initialized on the grid.
344  std::stringstream tempSS;
345  for (auto & configPair : fConfigurations)
346  {
347  tempSS.str("");
348  tempSS << configPair.second;
349  fConfigurationsStrings.push_back(std::make_pair(configPair.first, tempSS.str()));
350  }
351 
352  fInitialized = true;
353 
354  return fInitialized;
355 }
356 
367 {
368  bool returnValue = false;
369 
370  // If they were not streamed then the size of the vectors should not match
371  if (fConfigurations.size() != fConfigurationsStrings.size())
372  {
373  if (fInitialized == false)
374  {
375  // Not initialized, so the strings do not represent the nodes
376  AliFatalGeneral("AliYAMLConfiguration", "Attempted to re-initialize the YAML nodes, but the string based configurations are not available. Did you remember to call initialize?");
377  }
378 
379  for (const auto & configStrPair : fConfigurationsStrings)
380  {
381  YAML::Node node = YAML::Load(configStrPair.second);
382  fConfigurations.push_back(std::make_pair(configStrPair.first, node));
383  }
384 
385  returnValue = true;
386  }
387 
388  return returnValue;
389 }
390 
400 bool AliYAMLConfiguration::IsSharedValue(std::string & value) const
401 {
402  std::string stringToFind = "sharedParameters:";
403  std::size_t sharedParameterLocation = value.find(stringToFind);
404  if (sharedParameterLocation != std::string::npos)
405  {
406  value.erase(sharedParameterLocation, sharedParameterLocation + stringToFind.length());
407  return true;
408  }
409  // Return false otherwise
410  return false;
411 }
412 
419 void AliYAMLConfiguration::PrintConfiguration(std::ostream & stream, const std::pair<std::string, YAML::Node> & configPair) const
420 {
421  stream << "\nConfiguration Name: \"" << configPair.first << "\"\n\n";
422  stream << configPair.second << "\n";
423 }
424 
433 std::string AliYAMLConfiguration::toString(const int index) const
434 {
435  std::stringstream tempSS;
436 
437  if (index < 0) {
438  // Print header information
439  tempSS << std::boolalpha;
440  tempSS << "AliYAMLConfiguration:\n";
441  tempSS << "Initialized: " << fInitialized << "\n";
442  tempSS << "Prefix string: \"" << fPrefixString << "\"\n";
443  tempSS << "Delimiter: \"" << fDelimiter << "\"\n";
444  tempSS << "Configurations vector length: " << fConfigurations.size() << ", Configurations string vector length: " << fConfigurationsStrings.size() << "\n";
445  tempSS << "\nYAML Configurations:\n";
446 
447  // Print all configurations
448  for (auto configPair : fConfigurations) {
449  PrintConfiguration(tempSS, configPair);
450  }
451  }
452  else {
453  // Print a particular configuration
454  if (static_cast<const unsigned int>(index) < fConfigurations.size()) {
455  PrintConfiguration(tempSS, fConfigurations.at(index));
456  }
457  else {
458  tempSS << "Index " << index << " is out of range!\n";
459  }
460  }
461 
462  return tempSS.str();
463 }
464 
475 std::ostream & AliYAMLConfiguration::Print(std::ostream & in, const int index) const {
476  in << toString(index);
477  return in;
478 }
479 
488 std::ostream & AliYAMLConfiguration::Print(std::ostream & in, const std::string & configurationName) const {
489  std::ostream & result = Print(in, GetConfigurationIndexFromName(configurationName, fConfigurations));
490  return result;
491 }
492 
498 {
499  AliInfoStream() << toString();
500 }
501 
502 } // namespace Tools
503 } // namespace PWG
504 
514 std::ostream & operator<<(std::ostream & in, const PWG::Tools::AliYAMLConfiguration & myTask)
515 {
516  std::ostream & result = myTask.Print(in);
517  return result;
518 }
519 
const char * filename
Definition: TestFCM.C:1
friend std::ostream & operator<<(std::ostream &in, const AliYAMLConfiguration &myTask)
TSystem * gSystem
bool CompareConfigurations(const int config1, const int config2) const
bool WriteConfiguration(const std::string &filename, const unsigned int i) const
const std::pair< std::string, YAML::Node > & GetConfiguration(const int i) const
void WriteConfigurationToFilePath(const std::string &localFilename, std::string filename) const
bool fInitialized
True if the configurations have been initialized.
void SetupReadingConfigurationFilePath(std::string &filename, const std::string &fileIdentifier) const
bool DoesConfigurationExist(const int i) const
int GetConfigurationIndexFromName(const std::string &name) const
void Load()
Definition: UnfoldingHF.C:238
std::string fDelimiter
Delimiter character to separate each level of the request.
void PrintConfiguration(std::ostream &stream, const std::pair< std::string, YAML::Node > &configPair) const
bool IsSharedValue(std::string &value) const
std::ostream & Print(std::ostream &in, const int index=-1) const
Namespace for PWG framework classes.
std::string fPrefixString
Contains the prefix of any names base node names which should be removed.
int AddEmptyConfiguration(const std::string &configurationName)
Add YAML configuration at configurationFilename to available configurations.
std::vector< std::pair< std::string, YAML::Node > > fConfigurations
! Contains all YAML configurations. The first element has the highest precedence. ...
AliYAMLConfiguration(const std::string prefixString="AliEmcalCorrection", const std::string delimiterCharacter=":")
std::vector< std::pair< std::string, std::string > > fConfigurationsStrings
Contains all YAML configurations as strings so that they can be streamed.
YAML configuration class for AliPhysics.
bool GetPropertyFromNode(const YAML::Node &node, std::string propertyName, T &property) const
bool RemoveConfiguration(const unsigned int i)
int AddConfiguration(std::string configurationFilename, std::string configurationName="")
const char Option_t
Definition: External.C:48
bool DoesFileExist(const std::string &filename) const
std::string toString(const int index=-1) const