| 239 | } |
| 240 | |
| 241 | void Finish() { |
| 242 | Y_ENSURE(!InitialFillingDone); |
| 243 | InitialFillingDone = true; |
| 244 | TMap<i64, TVector<TString>> bySize; |
| 245 | for (const TString& fname: FileNames) { |
| 246 | TFile file(fname, OpenExisting | RdOnly); |
| 247 | bySize[file.GetLength()].push_back(fname); |
| 248 | } |
| 249 | for (const auto& bySizeElement: bySize) { |
| 250 | if (bySizeElement.second.size() > 1) { |
| 251 | TMap<TString, TVector<TString>, TMyFileComparator> byContents; |
| 252 | for (const TString& fname: bySizeElement.second) { |
| 253 | byContents[fname].push_back(fname); |
| 254 | } |
| 255 | for (const auto& byContentsElement: byContents) { |
| 256 | if (byContentsElement.second.size() > 1) { |
| 257 | const TString& rootName = byContentsElement.second.front(); |
| 258 | const TString& rootRecordName = FileNameToRecordName[rootName]; |
| 259 | for (const TString& fname: byContentsElement.second) { |
| 260 | if (fname != rootName) { |
| 261 | Synonyms[FileNameToRecordName[fname]] = rootRecordName; |
| 262 | } |
| 263 | } |
| 264 | } |
| 265 | } |
| 266 | } |
| 267 | } |
| 268 | FileNames.clear(); |
| 269 | FileNameToRecordName.clear(); |
| 270 | } |
| 271 | |
| 272 | bool InitialFillingDone = false; |
| 273 | TVector<TString> FileNames; |