otsdaq  v2_00_00
otsdaq_flatten_active_to_version.cc
1 #include <string>
2 #include <iostream>
3 #include <memory>
4 #include <cassert>
5 #include <dirent.h>
6 #include "otsdaq-core/ConfigurationInterface/ConfigurationManagerRW.h"
7 #include "otsdaq-core/ConfigurationInterface/ConfigurationInterface.h"
8 //#include "artdaq-database/StorageProviders/FileSystemDB/provider_filedb_index.h"
9 //#include "artdaq-database/JsonDocument/JSONDocument.h"
10 
11 //usage:
12 // otsdaq_flatten_active_to_version <flatVersion> <pathToSwapIn (optional)>
13 //
14 // if flatVersion is invalid or temporary nothing is saved in the new db
15 // (Note: this can be used to swap dbs using pathToSwapIn)
16 
17 using namespace ots;
18 
19 
20 void FlattenActiveConfigurationGroups(int argc, char* argv[])
21 {
22  std::cout << "=================================================\n";
23  std::cout << "=================================================\n";
24  std::cout << "=================================================\n";
25  std::cout << __COUT_HDR_FL__ << "\nFlattening Active Configuration Groups!" << std::endl;
26 
27  std::cout << "\n\nusage: Two arguments:\n\t pathToSwapIn <flatVersion> <pathToSwapIn (optional)> \n\n" <<
28  "\t Default values: flatVersion = 0, pathToSwapIn = \"\" \n\n" <<
29  std::endl;
30 
31  std::cout << "\n\nNote: you can optionally just swap databases (and not modify their contents at all)" <<
32  " by providing an invalid flatVersion of -1.\n\n" <<
33  std::endl;
34 
35  std::cout << "\n\nNote: This assumes artdaq db file type interface. " <<
36  "The current database/ will be moved to database_<linuxtime>/ " <<
37  "and if a pathToSwapIn is specified it will be copied to database/ " <<
38  "before saving the currently active groups.\n\n" <<
39  std::endl;
40 
41  std::cout << "argc = " << argc << std::endl;
42  for(int i = 0; i < argc; i++)
43  std::cout << "argv[" << i << "] = " << argv[i] << std::endl;
44 
45  if(argc < 2)
46  {
47  std::cout << "Must provide at least one parameter.";
48  return;
49  }
50 
51  //determine if "h"elp was first parameter
52  std::string flatVersionStr = argv[1];
53  if(flatVersionStr.find('h') != std::string::npos)
54  {
55  std::cout << "Recognized parameter 1. as a 'help' option. Usage was printed. Exiting." << std::endl;
56  return;
57  }
58 
59  int flatVersion = 0;
60  std::string pathToSwapIn = "";
61  if(argc >= 2)
62  sscanf(argv[1],"%d",&flatVersion);
63  if(argc >= 3)
64  pathToSwapIn = argv[2];
65 
66  std::cout << __COUT_HDR_FL__ << "flatVersion = " << flatVersion << std::endl;
67  std::cout << __COUT_HDR_FL__ << "pathToSwapIn = " << pathToSwapIn << std::endl;
68 
69 
70  //==============================================================================
71  //Define environment variables
72  // Note: normally these environment variables are set by StartOTS.sh
73 
74  //These are needed by otsdaq/otsdaq-core/ConfigurationDataFormats/ConfigurationInfoReader.cc [207]
75  setenv("CONFIGURATION_TYPE","File",1); //Can be File, Database, DatabaseTest
76  setenv("CONFIGURATION_DATA_PATH",(std::string(getenv("USER_DATA")) + "/ConfigurationDataExamples").c_str(),1);
77  setenv("CONFIGURATION_INFO_PATH",(std::string(getenv("USER_DATA")) + "/ConfigurationInfo").c_str(),1);
79 
80  //Some configuration plug-ins use getenv("SERVICE_DATA_PATH") in init() so define it
81  setenv("SERVICE_DATA_PATH",(std::string(getenv("USER_DATA")) + "/ServiceData").c_str(),1);
82 
83  //also xdaq envs for XDAQContextConfiguration
84  setenv("XDAQ_CONFIGURATION_DATA_PATH",(std::string(getenv("USER_DATA")) + "/XDAQConfigurations").c_str(),1);
85  setenv("XDAQ_CONFIGURATION_XML","otsConfigurationNoRU_CMake",1);
87 
88  //==============================================================================
89  //get prepared with initial source db
90 
91  //ConfigurationManager instance immediately loads active groups
92  ConfigurationManagerRW cfgMgrInst("flatten_admin");
93  ConfigurationManagerRW *cfgMgr = &cfgMgrInst;
94 
95  std::cout << __COUT_HDR_FL__ << "\n\n\nLoading activeGroupsMap..." << std::endl;
96 
97  //save group members to reform groups
98  std::map<std::string, std::pair<std::string, ConfigurationGroupKey> > activeGroupsMap =
99  cfgMgr->getActiveConfigurationGroups();
100 
101  std::map<std::string, std::map<std::string, ConfigurationVersion> > activeGroupMembersMap;
102  for(auto &activeGroupPair: activeGroupsMap)
103  {
104  if(activeGroupPair.second.second.isInvalid())
105  {
106  std::cout << __COUT_HDR_FL__ << "Skipping invalid " <<
107  activeGroupPair.first << std::endl;
108  continue;
109  }
110 
111  std::cout << __COUT_HDR_FL__ << "Loading members for " <<
112  activeGroupPair.first << "\t" <<
113  activeGroupPair.second.first << "(" << activeGroupPair.second.second << ")" <<
114  std::endl;
115 
116  activeGroupMembersMap[activeGroupPair.second.first] =
117  cfgMgr->getConfigurationInterface()->getConfigurationGroupMembers(
118  ConfigurationGroupKey::getFullGroupString(
119  activeGroupPair.second.first,activeGroupPair.second.second));
120  }
121 
122 
123  //==============================================================================
124  //manipulate directories
125  std::string currentDir = getenv("ARTDAQ_DATABASE_URI");
126 
127  if(currentDir.find("filesystemdb://") != 0)
128  {
129  __SS__ << "filesystemdb:// was not found in $ARTDAQ_DATABASE_URI!" << std::endl;
130  __COUT_ERR__ << "\n" << ss.str();
131  throw std::runtime_error(ss.str());
132  }
133 
134  currentDir = currentDir.substr(std::string("filesystemdb://").length());
135  while(currentDir.length() && currentDir[currentDir.length()-1] == '/') //remove trailing '/'s
136  currentDir = currentDir.substr(0,currentDir.length()-1);
137  std::string moveToDir = currentDir + "_" + std::to_string(time(0));
138 
139  std::cout << __COUT_HDR_FL__ << "Moving current directory: \t" << currentDir << std::endl;
140  std::cout << __COUT_HDR_FL__ << "\t... to: \t\t" << moveToDir << std::endl;
141 
142  if(argc < 2)
143  {
144  __SS__ << ("Aborting move! Must at least give version argument to flatten to!") << std::endl;
145  __COUT_ERR__ << "\n" << ss.str();
146  throw std::runtime_error(ss.str());
147  }
148 
149  rename(currentDir.c_str(),moveToDir.c_str());
150  FILE *fp = fopen((moveToDir + "/README_otsdaq_flatten.txt").c_str(),"a");
151  if(!fp)
152  std::cout << __COUT_HDR_FL__ << "\tError opening README file!" << std::endl;
153  else
154  {
155  time_t rawtime;
156  struct tm * timeinfo;
157  char buffer [200];
158 
159  time (&rawtime);
160  timeinfo = localtime (&rawtime);
161  strftime (buffer,200,"%b %d, %Y %I:%M%p %Z",timeinfo);
162 
163  fprintf(fp,"This database was moved from...\n\t %s \nto...\n\t %s \nat this time \n\t %lu \t %s\n\n\n",
164  currentDir.c_str(),moveToDir.c_str(),time(0),buffer);
165 
166  fclose(fp);
167  }
168 
169  if(pathToSwapIn != "")
170  {
171  DIR *dp;
172  if((dp = opendir(pathToSwapIn.c_str())) == 0)
173  {
174  std::cout << __COUT_HDR_FL__<< "ERROR:(" << errno << "). Can't open directory: " << pathToSwapIn << std::endl;
175  exit(0);
176  }
177  closedir(dp);
178 
179  std::cout << __COUT_HDR_FL__ << "Swapping in directory: \t" << pathToSwapIn << std::endl;
180  std::cout << __COUT_HDR_FL__ << "\t.. to: \t\t" << currentDir << std::endl;
181 
182  rename(pathToSwapIn.c_str(),currentDir.c_str());
183  FILE *fp = fopen((currentDir + "/README_otsdaq_flatten.txt").c_str(),"a");
184  if(!fp)
185  std::cout << __COUT_HDR_FL__ << "\tError opening README file!" << std::endl;
186  else
187  {
188  time_t rawtime;
189  struct tm * timeinfo;
190  char buffer [200];
191 
192  time (&rawtime);
193  timeinfo = localtime (&rawtime);
194  strftime (buffer,200,"%b %d, %Y %I:%M:%S%p %Z",timeinfo);
195 
196  fprintf(fp,"This database was moved from...\t %s \t to...\t %s at this time \t %lu \t %s\n\n",
197  pathToSwapIn.c_str(),currentDir.c_str(),time(0),buffer);
198  fclose(fp);
199  }
200  }
201 
202 
203  //==============================================================================
204  //save current active versions with flatVersion
205  // Note: do not try this at home kids.
206  ConfigurationInterface* theInterface_ = ConfigurationInterface::getInstance(false); //true for File interface, false for artdaq database;
207  ConfigurationView* cfgView;
208  ConfigurationBase* config;
209 
210  std::map<std::string, ConfigurationVersion> activeMap = cfgMgr->getActiveVersions();
211 
212 
213  //modify GroupAliasesConfiguration and VersionAliasesConfiguration to point
214  // at DEFAULT and flatVersion respectively
215 
216  const std::string groupAliasesName = "GroupAliasesConfiguration";
217  const std::string versionAliasesName = "VersionAliasesConfiguration";
218 
219 
220  //don't do anything more if flatVersion is not persistent
221  if(ConfigurationVersion(flatVersion).isInvalid() ||
222  ConfigurationVersion(flatVersion).isTemporaryVersion())
223  {
224  std::cout << __COUT_HDR_FL__ << "\n\nflatVersion " << ConfigurationVersion(flatVersion) <<
225  " is an invalid or temporary version. Skipping to end!" << std::endl;
226  goto CLEAN_UP;
227  }
228 
229 
230  //modify GroupAliasesConfiguration
231  if(activeMap.find(groupAliasesName) != activeMap.end())
232  {
233  std::cout << __COUT_HDR_FL__ << "\n\nModifying " << groupAliasesName << std::endl;
234  config = cfgMgr->getConfigurationByName(groupAliasesName);
235  cfgView = config->getViewP();
236 
237  unsigned int col1 = cfgView->findCol("GroupName");
238  unsigned int col2 = cfgView->findCol("GroupKey");
239 
240  //change all key entries to active groups to DEFAULT
241  for(unsigned int row = 0; row<cfgView->getNumberOfRows(); ++row )
242  for(auto &activeGroupPair: activeGroupsMap)
243  if(activeGroupPair.second.second.isInvalid()) continue;
244  else if(cfgView->getDataView()[row][col1] == activeGroupPair.second.first &&
245  cfgView->getDataView()[row][col2] == activeGroupPair.second.second.toString())
246  {
247  //found a matching group/key pair
248  std::cout << __COUT_HDR_FL__ <<
249  "Changing row " << row << " for " <<
250  cfgView->getDataView()[row][col1] << " key=" <<
251  cfgView->getDataView()[row][col2] << " to DEFAULT=" <<
252  ConfigurationGroupKey(ConfigurationGroupKey::getDefaultKey()) << std::endl;
253  cfgView->setValue(
254  ConfigurationGroupKey(ConfigurationGroupKey::getDefaultKey()).toString(),
255  row,col2);
256  break;
257  }
258 
259  }
260 
261  //modify VersionAliasesConfiguration
262  if(activeMap.find(versionAliasesName) != activeMap.end())
263  {
264  std::cout << __COUT_HDR_FL__ << "\n\nModifying " << versionAliasesName << std::endl;
265  config = cfgMgr->getConfigurationByName(versionAliasesName);
266  cfgView = config->getViewP();
267  unsigned int col1 = cfgView->findCol("ConfigurationName");
268  unsigned int col2 = cfgView->findCol("Version");
269 
270  //change all version entries to active tables to flatVersion
271  for(unsigned int row = 0; row<cfgView->getNumberOfRows(); ++row )
272  for(auto &activePair:activeMap)
273  if(cfgView->getDataView()[row][col1] == activePair.first &&
274  cfgView->getDataView()[row][col2] == activePair.second.toString())
275  {
276  //found a matching group/key pair
277  std::cout << __COUT_HDR_FL__ << "Changing row " << row << " for " <<
278  cfgView->getDataView()[row][col1] << " version=" <<
279  cfgView->getDataView()[row][col2] << " to flatVersion=" <<
280  ConfigurationVersion(flatVersion) << std::endl;
281  cfgView->setValue(ConfigurationVersion(flatVersion).toString(),row,col2);
282  break;
283  }
284  }
285 
286  std::cout << __COUT_HDR_FL__ << "\n\nChanging versions... " << std::endl;
287 
288  for(auto &activePair:activeMap)
289  {
290  std::cout << __COUT_HDR_FL__ << activePair.first << ":v" << activePair.second << std::endl;
291  //change the version of the active view to flatVersion and save it
292  config = cfgMgr->getConfigurationByName(activePair.first);
293  cfgView = config->getViewP();
294  cfgView->setVersion(ConfigurationVersion(flatVersion));
295  theInterface_->saveActiveVersion(config);
296  }
297 
298  //==============================================================================
299  //save the active groups with the new member flatVersions
300  // Note: do not try this at home kids.
301  for(auto &activeGroupMembersPair: activeGroupMembersMap)
302  {
303  std::cout << __COUT_HDR_FL__ << "Group " << activeGroupMembersPair.first << std::endl;
304 
305  for(auto &groupMemberPair: activeGroupMembersPair.second)
306  {
307  std::cout << __COUT_HDR_FL__ << "\t from...\t" <<
308  groupMemberPair.first << ":v" << groupMemberPair.second << std::endl;
309  groupMemberPair.second = flatVersion;
310  }
311 
312  for(auto &groupMemberPair: activeGroupMembersPair.second)
313  {
314  std::cout << __COUT_HDR_FL__ << "\t to...\t" <<
315  groupMemberPair.first << ":v" << groupMemberPair.second << std::endl;
316  }
317 
318  theInterface_->saveConfigurationGroup(activeGroupMembersPair.second,
319  ConfigurationGroupKey::getFullGroupString(
320  activeGroupMembersPair.first,
321  ConfigurationGroupKey(ConfigurationGroupKey::getDefaultKey())));
322  }
323 
324 CLEAN_UP:
325  //==============================================================================
326  std::cout << __COUT_HDR_FL__ << "\n\nEnd of Flattening Active Configuration Groups!\n\n\n" << std::endl;
327 
328 
329  std::cout << __COUT_HDR_FL__ << "Run the following to return to your previous database structure:" <<
330  std::endl;
331  std::cout << __COUT_HDR_FL__ << "\t otsdaq_flatten_active_to_version -1 " << moveToDir <<
332  "\n\n" << std::endl;
333 
334 
335  return;
336 }
337 
338 int main(int argc, char* argv[])
339 {
340  FlattenActiveConfigurationGroups(argc,argv);
341  return 0;
342 }
343 //BOOST_AUTO_TEST_SUITE_END()
344