1 #include "otsdaq/TableCore/TableBase.h"
6 #include "otsdaq/TableCore/TableInfoReader.h"
11 #define __MF_SUBJECT__ "TableBase"
13 #define __COUT_HDR__ ("TableBase-" + getTableName() + "\t<> ")
15 const std::string TableBase::GROUP_CACHE_PREPEND =
"GroupCache_";
16 const std::string TableBase::JSON_DOC_PREPEND =
"JSONDoc_";
25 std::string* accumulatedExceptions)
26 : MAX_VIEWS_IN_CACHE(20)
28 , tableName_(tableName)
30 , mockupTableView_(tableName)
34 __SS__ <<
"Do not allow anonymous table view construction!" << __E__;
46 std::cout <<
"TableBase Before traceTID=" << traceTID << __E__;
48 traceInit(trace_name(TRACE_NAME, __TRACE_FILE__, buf,
sizeof(buf)), 0);
49 std::cout <<
"TableBase After traceTID=" << traceTID << __E__;
50 __COUT__ <<
"TableBase TRACE reinit and Constructed." << __E__;
54 if(tableName.substr(0, TableBase::GROUP_CACHE_PREPEND.length()) ==
55 TableBase::GROUP_CACHE_PREPEND ||
56 tableName.substr(0, TableBase::JSON_DOC_PREPEND.length()) ==
57 TableBase::JSON_DOC_PREPEND)
59 __COUTT__ <<
"TableBase for '" << tableName <<
"' constructed." << __E__;
69 __COUT__ <<
"Reading..." << __E__;
72 std::string returnedExceptions = tableInfoReader.read(
this);
75 if(returnedExceptions !=
"")
76 __COUT_ERR__ << returnedExceptions << __E__;
78 if(accumulatedExceptions)
79 *accumulatedExceptions += std::string(
"\n") + returnedExceptions;
83 __SS__ <<
"Failure in tableInfoReader.read(this). "
84 <<
"Perhaps you need to run otsdaq_convert_config_to_table ?" << __E__;
85 __COUT_ERR__ <<
"\n" << ss.str();
86 if(accumulatedExceptions)
87 *accumulatedExceptions += std::string(
"\n") + ss.str();
93 __COUT__ <<
"Initializing..." << __E__;
97 getMockupViewP()->
init();
99 __COUT__ <<
"Init." << __E__;
101 catch(std::runtime_error&
104 if(accumulatedExceptions)
105 *accumulatedExceptions += std::string(
"\n") + e.what();
117 : MAX_VIEWS_IN_CACHE(1)
119 , tableName_(specialTableName)
120 , activeTableView_(0)
121 , mockupTableView_(specialTableName)
123 __COUT__ <<
"Special table '" << tableName_ <<
"' constructed. " << specialTable
140 std::string TableBase::getTypeId() {
return typeid(
this).name(); }
149 void TableBase::reset(
bool keepTemporaryVersions)
153 if(keepTemporaryVersions)
164 if(!activeTableView_)
166 __COUT_ERR__ <<
"ERROR: No active view set" << __E__;
169 activeTableView_->print(out);
177 if(!isStored(version))
181 mockupTableView_, version, mockupTableView_.getAuthor());
183 if(!isStored(version))
185 __SS__ <<
"IMPOSSIBLE ERROR: trimCache() is deleting the "
186 "latest view version "
187 << version <<
"!" << __E__;
193 __SS__ <<
"View to fill with mockup already exists: " << version
194 <<
". Cannot overwrite!" << __E__;
209 if(trimSize == (
unsigned int)-1)
216 time_t stalestTime = -1;
219 if(!viewPair.first.isTemporaryVersion())
221 if(stalestTime == -1 || viewPair.second.getLastAccessTime() < stalestTime)
223 versionToDelete = viewPair.first;
224 stalestTime = viewPair.second.getLastAccessTime();
232 __SS__ <<
"Can NOT have a stored view with an invalid version!" << __E__;
236 eraseView(versionToDelete);
251 if(it->first.isTemporaryVersion())
254 if(activeTableView_ &&
267 eraseView(targetVersion);
272 __SS__ <<
"Temporary trim target was a persistent version: " << targetVersion
294 __SS__ <<
"needleVersion does not exist: " << needleVersion << __E__;
298 const TableView* needleView = &(needleIt->second);
299 unsigned int rows = needleView->getNumberOfRows();
300 unsigned int cols = needleView->getNumberOfColumns();
303 unsigned int potentialMatchCount = 0;
309 auto viewPairReverseIterator =
tableViews_.rbegin();
310 for(; viewPairReverseIterator !=
tableViews_.rend(); ++viewPairReverseIterator)
312 if(viewPairReverseIterator->first == needleVersion)
314 if(viewPairReverseIterator->first == ignoreVersion)
316 if(viewPairReverseIterator->first.isTemporaryVersion())
319 if(viewPairReverseIterator->second.getNumberOfRows() != rows)
322 if(viewPairReverseIterator->second.getDataColumnSize() != cols ||
323 viewPairReverseIterator->second.getSourceColumnMismatch() != 0)
326 ++potentialMatchCount;
327 __COUTT__ <<
"Checking version... " << viewPairReverseIterator->first << __E__;
335 match = viewPairReverseIterator->second.getSourceColumnNames().size() ==
336 needleView->getSourceColumnNames().size();
339 for(
auto& haystackColName :
340 viewPairReverseIterator->second.getSourceColumnNames())
341 if(needleView->getSourceColumnNames().find(haystackColName) ==
342 needleView->getSourceColumnNames().end())
344 __COUT__ <<
"Found column name mismatch for '" << haystackColName
345 <<
"'... So allowing same data!" << __E__;
367 for(
unsigned int row = 0; match && row < rows; ++row)
369 for(
unsigned int col = 0; col < cols - 2;
371 if(viewPairReverseIterator->second.getDataView()[row][col] !=
372 needleView->getDataView()[row][col])
395 __COUT_INFO__ <<
"Duplicate version found: " << viewPairReverseIterator->first
397 return viewPairReverseIterator->first;
401 __COUT__ <<
"No duplicates found in " << potentialMatchCount <<
" potential matches."
412 std::stringstream* diffReport ,
413 std::map<std::string , std::vector<std::string /* colName */>>*
414 v1ModifiedRecords )
const
416 __COUTT__ <<
"Diffing version... " << v1 <<
" vs " << v2 << __E__;
421 __SS__ <<
"Version v" << v1 <<
" does not exist." << __E__;
428 __SS__ <<
"Version v" << v2 <<
" does not exist." << __E__;
432 const TableView* view1 = &(v1It->second);
433 const TableView* view2 = &(v2It->second);
434 unsigned int rows1 = view1->getNumberOfRows();
435 unsigned int cols1 = view1->getNumberOfColumns();
437 bool noDifference =
true;
445 if(view1->getSourceColumnNames().size() != view2->getSourceColumnNames().size())
447 __COUT__ <<
"Found column count mismatch for '"
448 << view1->getSourceColumnNames().size() <<
" vs "
449 << view2->getSourceColumnNames().size() << __E__;
452 *diffReport <<
"<li>Found column count mismatch. The v" << v1
453 <<
" column count is <b>'" << view1->getSourceColumnNames().size()
454 <<
"'</b> and the v" << v2 <<
" column count is <b>'"
455 << view2->getSourceColumnNames().size() <<
"'</b>." << __E__;
457 noDifference =
false;
462 for(
auto& colName1 : view1->getSourceColumnNames())
463 if(view2->getSourceColumnNames().find(colName1) ==
464 view2->getSourceColumnNames().end())
466 __COUT__ <<
"Found column name mismatch for '" << colName1 << __E__;
469 *diffReport <<
"<li>Found column name mismatch. The v" << v1
470 <<
" column <b>'" << colName1 <<
"'</b> was not found in v"
471 << v2 <<
"." << __E__;
473 noDifference =
false;
477 for(
auto& colName2 : view2->getSourceColumnNames())
478 if(view1->getSourceColumnNames().find(colName2) ==
479 view1->getSourceColumnNames().end())
481 __COUT__ <<
"Found column name mismatch for '" << colName2 << __E__;
484 *diffReport <<
"<li>Found column name mismatch. The v" << v1
485 <<
" does not have column <b>'" << colName2
486 <<
"'</b> that was found in v" << v2 <<
"." << __E__;
488 noDifference =
false;
493 if(rows1 != view2->getNumberOfRows())
495 __COUT__ <<
"Found row count mismatch for '" << rows1 <<
" vs "
496 << view2->getNumberOfRows() << __E__;
499 *diffReport <<
"<li>Found row count mismatch. The v" << v1
500 <<
" row count is <b>'" << rows1 <<
"'</b> and the v" << v2
501 <<
" row count is <b>'" << view2->getNumberOfRows() <<
"'</b>."
504 noDifference =
false;
510 std::set<std::string > uidSet1, uidSet2;
511 for(
unsigned int row = 0; row < rows1; ++row)
512 uidSet1.insert(view1->getDataView()[row][view1->
getColUID()]);
513 for(
unsigned int row = 0; row < view2->getNumberOfRows(); ++row)
514 uidSet2.insert(view2->getDataView()[row][view2->
getColUID()]);
516 for(
auto& uid1 : uidSet1)
517 if(uidSet2.find(uid1) == uidSet2.end())
519 __COUT__ <<
"Found record name mismatch for '" << uid1 << __E__;
522 *diffReport <<
"<li>Found record name mismatch. The v" << v1
523 <<
" record <b>'" << uid1 <<
"'</b> was not found in v" << v2
526 noDifference =
false;
530 for(
auto& uid2 : uidSet2)
531 if(uidSet1.find(uid2) == uidSet1.end())
533 __COUT__ <<
"Found record name mismatch for '" << uid2 << __E__;
536 *diffReport <<
"<li>Found record name mismatch. v" << v1
537 <<
" does not have record <b>'" << uid2
538 <<
"'</b> that was found in v" << v2 <<
"." << __E__;
540 noDifference =
false;
545 unsigned int row2, col2;
546 for(
unsigned int row = 0; row < rows1 && row < view2->getNumberOfRows(); ++row)
550 if(view1->getDataView()[row][view1->
getColUID()] !=
551 view2->getDataView()[row2][view2->
getColUID()])
553 bool foundUid2 =
false;
555 for(row2 = 0; row2 < view2->getNumberOfRows(); ++row2)
556 if(view1->getDataView()[row][view1->
getColUID()] ==
557 view2->getDataView()[row2][view2->
getColUID()])
562 __COUTT__ <<
"Found row ? '" << foundUid2 <<
" " << row <<
"," << row2
568 __COUTT__ <<
"Found row "
569 <<
" " << row <<
"," << row2 << __E__;
570 for(
unsigned int col = 0;
571 col < cols1 - 2 && col < view2->getNumberOfColumns() - 2;
576 if(view1->getColumnInfo(col).getName() !=
577 view2->getColumnInfo(col2).getName())
579 bool foundCol2 =
false;
581 for(col2 = 0; col2 < view2->getNumberOfColumns() - 2; ++col2)
582 if(view1->getColumnInfo(col).getName() ==
583 view2->getColumnInfo(col2).getName())
589 __COUTT__ <<
"Found column ? '" << foundCol2 <<
" " << col <<
"," << col2
595 __COUTT__ <<
"Found column "
596 <<
" " << col <<
"," << col2 << __E__;
597 if(view1->getDataView()[row][col] != view2->getDataView()[row2][col2])
599 __COUT__ <<
"Found column value mismatch for '" << row <<
"," << col
600 <<
" " << view1->getDataView()[row][col] << __E__;
603 *diffReport <<
"<li><b>" << view1->getColumnInfo(col).getName()
604 <<
"</b> value mismatch at v" << v1 <<
" {UID,r,c}:{<b>"
605 << view1->getDataView()[row][view1->
getColUID()]
606 <<
"</b>," << row <<
"," << col <<
"}: <b>'"
607 << view1->getDataView()[row][col] <<
"'</b> vs value in v"
608 << v2 <<
": <b>'" << view2->getDataView()[row2][col2]
609 <<
"'</b>." << __E__;
611 noDifference =
false;
615 if(v1ModifiedRecords)
616 (*v1ModifiedRecords)[view1->getDataView()[row][view1->
getColUID()]]
617 .push_back(view1->getColumnInfo(col).getName());
622 if(noDifference && diffReport)
623 *diffReport <<
"<li>No difference found between v" << v1 <<
" and v" << v2 <<
"."
630 void TableBase::changeVersionAndActivateView(
TableVersion temporaryVersion,
636 __SS__ <<
"ERROR: Temporary view version " << temporaryVersion
637 <<
" doesn't exists!" << __E__;
642 __SS__ <<
"ERROR: Attempting to create an invalid version " << version
643 <<
"! Did you really run out of versions? (this should never happen)"
649 __COUT_WARN__ <<
"WARNING: View version " << version
650 <<
" already exists! Overwriting." << __E__;
654 emplacePair.first->second.copy(tmpIt->second, version, tmpIt->second.getAuthor());
655 setActiveView(version);
656 eraseView(temporaryVersion);
660 bool TableBase::isStored(
const TableVersion& version)
const
668 if(!isStored(version))
671 if(activeTableView_ &&
684 const std::string& TableBase::getTableDescription(
void)
const
686 return tableDescription_;
692 return getView().getVersion();
700 std::set<TableVersion> retSet = getStoredVersions();
701 if(retSet.size() && !retSet.rbegin()->isTemporaryVersion())
703 return tableViews_.find(*(retSet.rbegin()))->second.getNumberOfColumns() !=
704 mockupTableView_.getNumberOfColumns();
711 std::set<TableVersion> TableBase::getStoredVersions(
void)
const
713 std::set<TableVersion> retSet;
715 retSet.emplace(configs.first);
727 if(viewPair.first.isTemporaryVersion())
729 else if(viewPair.first.isInvalid())
739 __COUT__ <<
"There is an invalid version now!.. where did it come from?"
753 if(version != TableVersion::INVALID)
758 __SS__ <<
"Table '" << tableName_ <<
"' does not have version v" << version
759 <<
" in the cache." << __E__;
763 if(!activeTableView_)
765 __SS__ <<
"There is no active table view setup! Please check your system "
770 return *activeTableView_;
778 if(version != TableVersion::INVALID)
783 __SS__ <<
"Table '" << tableName_ <<
"' does not have version v" << version
784 <<
" in the cache." << __E__;
788 if(!activeTableView_)
790 __SS__ <<
"There is no active table view setup! Please check your system "
795 return activeTableView_;
799 TableView* TableBase::getMockupViewP(
void) {
return &mockupTableView_; }
805 void TableBase::setTableDescription(
const std::string& tableDescription)
807 tableDescription_ = tableDescription;
822 if(!isStored(version))
827 __SS__ <<
"\nsetActiveView() ERROR: View with version " << version
828 <<
" has never been stored before!" << __E__;
834 if(
tableViews_.at(version).getVersion() != version)
836 __SS__ <<
"Something has gone very wrong with the version handling!" << __E__;
855 const std::string& author,
856 const std::string& mergeApproach ,
857 std::map<std::pair<std::string /*original table*/, std::string /*original uidB*/>,
858 std::string >& uidConversionMap,
860 std::pair<std::string ,
861 std::pair<std::string /*group linkid*/, std::string /*original gidB*/>>,
862 std::string >& groupidConversionMap,
863 bool fillRecordConversionMaps,
864 bool applyRecordConversionMaps,
865 bool generateUniqueDataColumns ,
866 std::stringstream* mergeReport )
868 __COUT__ <<
"mergeViews starting..." << __E__;
880 if(!(mergeApproach ==
"Rename" || mergeApproach ==
"Replace" ||
881 mergeApproach ==
"Skip"))
883 __SS__ <<
"Error! Invalid merge approach '" << mergeApproach <<
".'" << __E__;
888 if(sourceViewA.getNumberOfColumns() != mockupTableView_.getNumberOfColumns())
890 __SS__ <<
"Error! Number of Columns of source view A must match destination "
892 <<
"Dimension of source is [" << sourceViewA.getNumberOfColumns()
893 <<
"] and of destination mockup is ["
894 << mockupTableView_.getNumberOfColumns() <<
"]." << __E__;
898 if(sourceViewB.getNumberOfColumns() != mockupTableView_.getNumberOfColumns())
900 __SS__ <<
"Error! Number of Columns of source view B must match destination "
902 <<
"Dimension of source is [" << sourceViewB.getNumberOfColumns()
903 <<
"] and of destination mockup is ["
904 << mockupTableView_.getNumberOfColumns() <<
"]." << __E__;
914 (*mergeReport) <<
"\n'" << mergeApproach <<
"'-Merging table '" <<
getTableName()
915 <<
"' A=v" << sourceViewA.getVersion() <<
" with B=v"
916 << sourceViewB.getVersion() << __E__;
918 if(fillRecordConversionMaps && mergeApproach ==
"Rename")
920 __COUT__ <<
"Filling record conversion map." << __E__;
930 unsigned int uniqueId;
931 std::string uniqueIdString, uniqueIdBase;
932 char indexString[1000];
934 unsigned int numericStartIndex;
937 for(
unsigned int cb = 0; cb < sourceViewB.getNumberOfColumns(); ++cb)
940 if(!(sourceViewA.getColumnInfo(cb).
isUID() ||
941 sourceViewA.getColumnInfo(cb).
isGroupID()))
944 __COUT__ <<
"Have an ID column: " << cb <<
" "
945 << sourceViewA.getColumnInfo(cb).getType() << __E__;
948 if(sourceViewA.getColumnInfo(cb).getType() !=
949 sourceViewB.getColumnInfo(cb).getType() ||
950 sourceViewA.getColumnInfo(cb).getType() !=
951 mockupTableView_.getColumnInfo(cb).getType())
953 __SS__ <<
"Error! " << sourceViewA.getColumnInfo(cb).getType()
955 <<
" of source view A must match source B and destination mock-up "
957 <<
" Column of source B is ["
958 << sourceViewA.getColumnInfo(cb).getType()
959 <<
"] and of destination mockup is ["
960 << mockupTableView_.getColumnInfo(cb).getType() <<
"]." << __E__;
966 std::vector<std::string >
969 if(sourceViewA.getColumnInfo(cb).
isGroupID())
974 for(
const auto& bGroupid : bGroupids)
976 if(aGroupids.find(bGroupid) == aGroupids.end())
980 __COUT__ <<
"found conflict: " <<
getTableName() <<
"/" << bGroupid
985 const std::string& str = bGroupid;
986 numericStartIndex = str.size();
989 while(numericStartIndex - 1 < str.size() &&
990 str[numericStartIndex - 1] >=
'0' &&
991 str[numericStartIndex - 1] <=
'9')
994 if(numericStartIndex < str.size())
996 uniqueId = atoi(str.substr(numericStartIndex).c_str()) + 1;
997 uniqueIdBase = str.substr(0, numericStartIndex);
1005 __COUTV__(uniqueIdBase);
1006 __COUTV__(uniqueId);
1011 sprintf(indexString,
"%u", uniqueId);
1012 uniqueIdString = uniqueIdBase + indexString;
1013 __COUTV__(uniqueIdString);
1017 if(aGroupids.find(uniqueIdString) != aGroupids.end())
1019 if(!found && bGroupids.find(uniqueIdString) != bGroupids.end())
1021 if(!found && bGroupids.find(uniqueIdString) != bGroupids.end())
1023 for(ra = 0; !found && ra < localConvertedIds.size(); ++ra)
1024 if(localConvertedIds[ra] == uniqueIdString)
1030 sprintf(indexString,
"%u", uniqueId);
1031 uniqueIdString = uniqueIdBase + indexString;
1032 __COUTV__(uniqueIdString);
1036 if(aGroupids.find(uniqueIdString) != aGroupids.end())
1039 bGroupids.find(uniqueIdString) != bGroupids.end())
1042 bGroupids.find(uniqueIdString) != bGroupids.end())
1044 for(ra = 0; !found && ra < localConvertedIds.size(); ++ra)
1045 if(localConvertedIds[ra] == uniqueIdString)
1051 __COUTV__(uniqueIdString);
1053 groupidConversionMap
1054 [std::pair<std::string ,
1055 std::pair<std::string ,
1058 std::pair<std::string ,
1061 bGroupid))] = uniqueIdString;
1062 localConvertedIds.push_back(uniqueIdString);
1069 <<
"Found conflicting B groupID for linkIndex '"
1071 <<
"' and renamed '" << bGroupid <<
"' to '" << uniqueIdString
1082 for(
unsigned int rb = 0; rb < sourceViewB.getNumberOfRows(); ++rb)
1086 for(ra = 0; ra < sourceViewA.getDataView().size(); ++ra)
1098 __COUT__ <<
"found conflict: " <<
getTableName() <<
"/"
1099 << sourceViewB.getDataView()[rb][cb] << __E__;
1103 const std::string& str = sourceViewB.getDataView()[rb][cb];
1104 numericStartIndex = str.size();
1107 while(numericStartIndex - 1 < str.size() &&
1108 str[numericStartIndex - 1] >=
'0' &&
1109 str[numericStartIndex - 1] <=
'9')
1110 --numericStartIndex;
1112 if(numericStartIndex < str.size())
1114 uniqueId = atoi(str.substr(numericStartIndex).c_str()) + 1;
1115 uniqueIdBase = str.substr(0, numericStartIndex);
1123 __COUTV__(uniqueIdBase);
1124 __COUTV__(uniqueId);
1129 sprintf(indexString,
"%u", uniqueId);
1130 uniqueIdString = uniqueIdBase + indexString;
1131 __COUTV__(uniqueIdString);
1135 for(ra = 0; !found && ra < sourceViewA.getDataView().size(); ++ra)
1138 for(ra = 0; !found && ra < sourceViewB.getDataView().size(); ++ra)
1144 for(ra = 0; !found && ra < localConvertedIds.size(); ++ra)
1145 if(localConvertedIds[ra] == uniqueIdString)
1151 sprintf(indexString,
"%u", uniqueId);
1152 uniqueIdString = uniqueIdBase + indexString;
1153 __COUTV__(uniqueIdString);
1157 for(ra = 0; !found && ra < sourceViewA.getDataView().size();
1161 for(ra = 0; !found && ra < sourceViewB.getDataView().size();
1168 for(ra = 0; !found && ra < localConvertedIds.size(); ++ra)
1169 if(localConvertedIds[ra] == uniqueIdString)
1175 __COUTV__(uniqueIdString);
1177 uidConversionMap[std::pair<std::string ,
1181 localConvertedIds.push_back(uniqueIdString);
1186 (*mergeReport) <<
"\t"
1187 <<
"Found conflicting B UID and renamed '"
1189 << uniqueIdString <<
"'" << __E__;
1200 __COUT__ <<
"Not filling record conversion map." << __E__;
1202 if(!applyRecordConversionMaps)
1204 __COUT__ <<
"Not applying record conversion map." << __E__;
1209 __COUT__ <<
"Applying record conversion map." << __E__;
1217 __COUT__ <<
"Merging from (A) " << sourceViewA.getTableName() <<
"_v"
1218 << sourceViewA.getVersion() <<
" and (B) " << sourceViewB.getTableName()
1219 <<
"_v" << sourceViewB.getVersion() <<
" to " <<
getTableName() <<
"_v"
1220 << destinationVersion <<
" with approach '" << mergeApproach <<
".'"
1232 .copy(sourceViewA, destinationVersion, author));
1234 unsigned int destRow, destSize = destinationView->getDataView().size();
1237 std::map<std::pair<std::string , std::string >,
1238 std::string >::iterator uidConversionIt;
1239 std::map<std::pair<std::string ,
1240 std::pair<std::string ,
1242 std::string >::iterator groupidConversionIt;
1245 std::pair<
unsigned int ,
unsigned int > linkPair;
1249 unsigned int colUID = mockupTableView_.
getColUID();
1252 for(
unsigned int rb = 0; rb < sourceViewB.getNumberOfRows(); ++rb)
1254 if(mergeApproach ==
"Rename")
1264 destRow = destinationView->
copyRows(
1270 generateUniqueDataColumns );
1274 for(cb = 0; cb < sourceViewB.getNumberOfColumns(); ++cb)
1280 __COUT__ <<
"Checking UID link... col=" << cb << __E__;
1284 if((uidConversionIt = uidConversionMap.find(
1285 std::pair<std::string ,
1289 rb, linkPair.second)))) != uidConversionMap.end())
1291 __COUT__ <<
"Found entry to remap: "
1292 << sourceViewB.getDataView()[rb][linkPair.second]
1293 <<
" ==> " << uidConversionIt->second << __E__;
1298 <<
"Found entry to remap [r,c]=[" << rb <<
"," << cb
1301 << sourceViewB.getDataView()[rb][linkPair.second]
1302 <<
" ==> [" << destRow <<
"," << linkPair.second
1303 << uidConversionIt->second << __E__;
1305 uidConversionIt->second, destRow, linkPair.second);
1310 __COUT__ <<
"Checking GroupID link... col=" << cb << __E__;
1314 if((groupidConversionIt = groupidConversionMap.find(
1315 std::pair<std::string ,
1316 std::pair<std::string ,
1319 std::pair<std::string ,
1323 rb, linkPair.second))))) !=
1324 groupidConversionMap.end())
1326 __COUT__ <<
"Found entry to remap: "
1327 << sourceViewB.getDataView()[rb][linkPair.second]
1328 <<
" ==> " << groupidConversionIt->second << __E__;
1333 <<
"Found entry to remap [r,c]=[" << rb <<
"," << cb
1336 << sourceViewB.getDataView()[rb][linkPair.second]
1337 <<
" ==> [" << destRow <<
"," << linkPair.second
1338 <<
"] " << groupidConversionIt->second << __E__;
1340 groupidConversionIt->second, destRow, linkPair.second);
1343 else if(sourceViewB.getColumnInfo(cb).
isUID())
1345 __COUT__ <<
"Checking UID... col=" << cb << __E__;
1346 if((uidConversionIt = uidConversionMap.find(
1347 std::pair<std::string ,
1351 uidConversionMap.end())
1353 __COUT__ <<
"Found entry to remap: "
1354 << sourceViewB.getDataView()[rb][cb] <<
" ==> "
1355 << uidConversionIt->second << __E__;
1360 <<
"Found entry to remap [r,c]=[" << rb <<
"," << cb
1362 <<
": " << sourceViewB.getDataView()[rb][cb]
1363 <<
" ==> [" << destRow <<
"," << cb <<
"] "
1364 << uidConversionIt->second << __E__;
1366 uidConversionIt->second, destRow, cb);
1369 else if(sourceViewB.getColumnInfo(cb).
isGroupID())
1371 __COUT__ <<
"Checking GroupID... col=" << cb << __E__;
1372 if((groupidConversionIt = groupidConversionMap.find(
1373 std::pair<std::string ,
1374 std::pair<std::string ,
1377 std::pair<std::string ,
1381 groupidConversionMap.end())
1383 __COUT__ <<
"Found entry to remap: "
1384 << sourceViewB.getDataView()[rb][cb] <<
" ==> "
1385 << groupidConversionIt->second << __E__;
1390 <<
"Found entry to remap [r,c]=[" << rb <<
"," << cb
1391 <<
"]" << sourceViewB.getDataView()[rb][cb]
1392 <<
" ==> [" << destRow <<
"," << cb <<
"] "
1393 << groupidConversionIt->second << __E__;
1395 groupidConversionIt->second, destRow, cb);
1402 if(strb.size() >
getTableName().size() + 2 && strb[0] ==
'/')
1405 __COUT__ <<
"Checking col" << cb <<
" " << strb << __E__;
1408 for(
const auto& mapPairToPair : uidConversionMap)
1410 if((stri = strb.find(mapPairToPair.first.first +
"/" +
1411 mapPairToPair.first.second)) !=
1414 __COUT__ <<
"Found a text link match (stri=" << stri
1416 << (mapPairToPair.first.first +
"/" +
1417 mapPairToPair.first.second)
1418 <<
" ==> " << mapPairToPair.second << __E__;
1422 strb.substr(0, stri) +
1423 (mapPairToPair.first.first +
"/" +
1424 mapPairToPair.first.second) +
1426 (mapPairToPair.first.first +
"/" +
1427 mapPairToPair.first.second)
1433 <<
"Found entry to remap: "
1434 << sourceViewB.getDataView()[rb][cb] <<
" ==> "
1435 << destinationView->getDataView()[destRow][cb]
1441 <<
"Found entry to remap [r,c]=[" << rb <<
","
1443 << sourceViewB.getDataView()[rb][cb]
1444 <<
" ==> [" << destRow <<
"," << cb <<
"] "
1445 << destinationView->getDataView()[destRow][cb]
1461 for(destRow = 0; destRow < destSize; ++destRow)
1470 __COUT__ <<
"No " << mergeApproach <<
" conflict: " << __E__;
1472 if(mergeApproach ==
"replace" || mergeApproach ==
"skip")
1477 author, sourceViewB, rb, 1 );
1486 __COUT__ <<
"found " << mergeApproach
1487 <<
" conflict: " << sourceViewB.getDataView()[rb][colUID] << __E__;
1489 if(mergeApproach ==
"replace")
1494 <<
"Found UID conflict, replacing A with B record row=" << rb
1495 <<
" " << sourceViewB.getDataView()[rb][colUID] << __E__;
1505 destinationView->
copyRows(author, sourceViewB, rb, 1 );
1507 else if(mergeApproach ==
"skip")
1512 <<
"Found UID conflict, skipping B record row=" << rb <<
" "
1513 << sourceViewB.getDataView()[rb][colUID] << __E__;
1517 destinationView->print();
1521 __COUT_ERR__ <<
"Failed to merge " << sourceViewA.getTableName() <<
"_v"
1522 << sourceViewA.getVersion() <<
" and " << sourceViewB.getTableName()
1523 <<
"_v" << sourceViewB.getVersion() <<
" into " <<
getTableName()
1524 <<
"_v" << destinationVersion << __E__;
1525 __COUT_WARN__ <<
"Deleting the failed destination version " << destinationVersion
1527 eraseView(destinationVersion);
1531 return destinationVersion;
1544 const std::string& author,
1545 bool looseColumnMatching )
1548 if(!looseColumnMatching &&
1549 sourceView.getNumberOfColumns() != mockupTableView_.getNumberOfColumns())
1551 __SS__ <<
"Error! Number of Columns of source view must match destination "
1553 <<
"Dimension of source is [" << sourceView.getNumberOfColumns()
1554 <<
"] and of destination mockup is ["
1555 << mockupTableView_.getNumberOfColumns() <<
"]." << __E__;
1563 __SS__ <<
"Error! Asked to copy a view with a conflicting version: "
1564 << destinationVersion << __E__;
1571 __COUT__ <<
"Copying from " << sourceView.getTableName() <<
"_v"
1572 << sourceView.getVersion() <<
" to " <<
getTableName() <<
"_v"
1573 << destinationVersion << __E__;
1578 tableViews_.at(destinationVersion).copy(sourceView, destinationVersion, author);
1582 __COUT_ERR__ <<
"Failed to copy from " << sourceView.getTableName() <<
"_v"
1583 << sourceView.getVersion() <<
" to " <<
getTableName() <<
"_v"
1584 << destinationVersion << __E__;
1585 __COUT_WARN__ <<
"Deleting the failed destination version " << destinationVersion
1587 eraseView(destinationVersion);
1591 return destinationVersion;
1612 while(isStored(tmpVersion) &&
1615 if(isStored(tmpVersion) || tmpVersion.
isInvalid())
1617 __SS__ <<
"Invalid destination temporary version: " << destTemporaryViewVersion
1618 <<
". Expected next temporary version < " << tmpVersion << __E__;
1622 if(sourceViewVersion ==
1623 TableVersion::INVALID ||
1626 if(sourceViewVersion != -1)
1628 __SS__ <<
"ERROR: sourceViewVersion " << sourceViewVersion <<
" not found. "
1629 <<
"Invalid source version. Version requested is not stored (yet?) or "
1634 __COUTT__ <<
"Using Mock-up view" << __E__;
1637 .copy(mockupTableView_, tmpVersion, mockupTableView_.getAuthor());
1652 <<
"createTemporaryView() Source view failed init(). "
1653 <<
"This is being ignored (hopefully the new copy is being fixed)."
1678 __SS__ <<
"Invalid destination temporary version: " << tmpVersion << __E__;
1701 __SS__ <<
"Invalid destination next version: " << tmpVersion << __E__;
1716 __SS__ <<
getTableName() <<
":: Error! Temporary version not found!" << __E__;
1729 unsigned int configPos = (
unsigned int)std::string::npos;
1730 if(isTableName && (configPos = str.find(
"Table")) != str.size() - strlen(
"Table"))
1735 std::string capsStr =
"";
1736 for(
unsigned int c = 0; c < str.size(); ++c)
1737 if(str[c] >=
'A' && str[c] <=
'Z')
1740 if(c == configPos ||
1741 (c && str[c - 1] >=
'a' &&
1742 str[c - 1] <=
'z') ||
1743 (c && str[c - 1] >=
'A' &&
1744 str[c - 1] <=
'Z' &&
1745 c + 1 < str.size() && str[c + 1] >=
'a' && str[c + 1] <=
'z'))
1749 else if(str[c] >=
'a' && str[c] <=
'z')
1750 capsStr += char(str[c] - 32);
1751 else if(str[c] >=
'0' && str[c] <=
'9')
1756 if((str.substr(0, TableBase::GROUP_CACHE_PREPEND.length()) ==
1757 TableBase::GROUP_CACHE_PREPEND ||
1758 str.substr(0, TableBase::JSON_DOC_PREPEND.length()) ==
1759 TableBase::JSON_DOC_PREPEND) &&
1766 std::stringstream ss;
1767 ss << __COUT_HDR_FL__
1768 <<
"TableBase::convertToCaps: Invalid character found in name (allowed: "
1770 << str <<
"'" << __E__;
1771 TLOG(TLVL_ERROR) << ss.str();
const std::string & getTableName(void) const
Getters.
std::map< TableVersion, TableView > tableViews_
TableVersion createTemporaryView(TableVersion sourceViewVersion=TableVersion(), TableVersion destTemporaryViewVersion=TableVersion::getNextTemporaryVersion())
source of -1, from MockUp, else from valid view version
void setupMockupView(TableVersion version)
bool diffTwoVersions(TableVersion v1, TableVersion v2, std::stringstream *diffReport=0, std::map< std::string, std::vector< std::string >> *v1ModifiedRecords=0) const
TableBase(bool specialTable, const std::string &specialTableName)
void trimTemporary(TableVersion targetVersion=TableVersion())
TableVersion mergeViews(const TableView &sourceViewA, const TableView &sourceViewB, TableVersion destinationVersion, const std::string &author, const std::string &mergeApproach, std::map< std::pair< std::string, std::string >, std::string > &uidConversionMap, std::map< std::pair< std::string, std::pair< std::string, std::string > >, std::string > &groupidConversionMap, bool fillRecordConversionMaps, bool applyRecordConversionMaps, bool generateUniqueDataColumns=false, std::stringstream *mergeRepoert=nullptr)
unsigned int getNumberOfStoredViews(void) const
TableVersion checkForDuplicate(TableVersion needleVersion, TableVersion ignoreVersion=TableVersion()) const
bool isActive(void)
isActive
static std::string convertToCaps(std::string &str, bool isConfigName=false)
virtual void init(ConfigurationManager *configManager)
Methods.
TableView * getTemporaryView(TableVersion temporaryVersion)
const unsigned int MAX_VIEWS_IN_CACHE
TableVersion getNextVersion(void) const
const TableVersion & getViewVersion(void) const
always the active one
TableVersion copyView(const TableView &sourceView, TableVersion destinationVersion, const std::string &author, bool looseColumnMatching=false)
bool latestAndMockupColumnNumberMismatch(void) const
void setTableName(const std::string &tableName)
Setters.
void print(std::ostream &out=std::cout) const
always prints active view
TableVersion getNextTemporaryVersion(void) const
void trimCache(unsigned int trimSize=-1)
bool isInvalid(void) const
isInvalid
static TableVersion getNextVersion(const TableVersion &version=TableVersion())
bool isTemporaryVersion(void) const
static TableVersion getNextTemporaryVersion(const TableVersion &version=TableVersion())
bool isChildLinkUID(void) const
std::string getChildLinkIndex(void) const
getChildLinkIndex
bool isChildLink(void) const
bool isUID(void) const
isUID
bool isGroupID(void) const
bool isChildLinkGroupID(void) const
void setValueAsString(const std::string &value, unsigned int row, unsigned int col)
bool getChildLink(const unsigned int &col, bool &isGroup, std::pair< unsigned int, unsigned int > &linkPair) const
unsigned int copyRows(const std::string &author, const TableView &src, unsigned int srcOffsetRow=0, unsigned int srcRowsToCopy=(unsigned int) -1, unsigned int destOffsetRow=(unsigned int) -1, unsigned char generateUniqueDataColumns=false, const std::string &baseNameAutoUID="")
std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
std::set< std::string > getSetOfGroupIDs(const std::string &childLinkIndex, unsigned int row=-1) const
unsigned int getColUID(void) const
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
static std::string stackTrace(void)