File indexing completed on 2023-03-17 10:39:11
0001
0002
0003
0004 #include <fstream>
0005 #include <iostream>
0006
0007 #include "Alignment/Geners/interface/BinaryArchiveBase.hh"
0008 #include "Alignment/Geners/interface/CPP11_auto_ptr.hh"
0009 #include "Alignment/Geners/interface/CatalogIO.hh"
0010 #include "Alignment/Geners/interface/ContiguousCatalog.hh"
0011 #include "Alignment/Geners/interface/IOException.hh"
0012 #include "Alignment/Geners/interface/streamposIO.hh"
0013
0014 #include "CmdLine.hh"
0015
0016 using namespace gs;
0017 using namespace std;
0018
0019 static void print_usage(const char *progname) {
0020 cout << "\nUsage: " << progname << " archive_name [annotation]\n\n"
0021 << "This program recovers the \"geners\" catalog data from binary "
0022 "archives.\n"
0023 << "The recovery is possible only if the archive mode string included "
0024 "the\n"
0025 << "\"cat=i\" section which instructs the binary archive to write a "
0026 "duplicate\n"
0027 << "copy of item metadata into the data stream. This mode of operation\n"
0028 << "is recommended in the development stage of your project, so that "
0029 "the\n"
0030 << "catalog can be recovered even after an unexpected program crash.\n\n"
0031 << "The first command line argument is the name of the \"geners\" "
0032 "archive\n"
0033 << "without extension or data file number. The second argument is "
0034 "optional.\n"
0035 << "If provided, it will become the annotation string added to the "
0036 "recovered\n"
0037 << "catalog.\n"
0038 << endl;
0039 }
0040
0041 namespace {
0042 class CatalogRecovery : public BinaryArchiveBase {
0043 inline std::ostream &plainOutputStream() { return f_; }
0044
0045 inline std::istream &plainInputStream(unsigned long long ,
0046 unsigned * ,
0047 unsigned long long * ) {
0048 return f_;
0049 }
0050
0051 inline void openFile(const unsigned long count) {
0052 std::ostringstream os;
0053 os << AbsArchive::name() << '.' << count << ".gsbd";
0054 const std::string &fname = os.str();
0055 openDataFile(f_, fname.c_str());
0056 cout << "Processing file " << fname << "\n";
0057 cout.flush();
0058 }
0059
0060 inline unsigned long long addToCatalog(const AbsRecord & ,
0061 unsigned ,
0062 unsigned long long ) {
0063 return 0ULL;
0064 }
0065
0066 fstream f_;
0067 ContiguousCatalog cat_;
0068
0069 public:
0070 inline CatalogRecovery(const char *name) : BinaryArchiveBase(name, "r") {}
0071
0072 inline ~CatalogRecovery() {
0073 if (f_.is_open())
0074 f_.close();
0075 }
0076
0077 inline std::string catalogFileName() const { return AbsArchive::name() + ".gsbmf"; }
0078
0079 inline unsigned long long processFile(const unsigned long fileNumber) {
0080 openFile(fileNumber);
0081 if (!injectMetadata())
0082 throw IOInvalidData(
0083 "Item metadata was not written into the data stream. "
0084 "Catalog can not be recovered.");
0085 assert(catalogEntryClassId());
0086 assert(itemLocationClassId());
0087
0088 const std::streampos zeropos(0);
0089 unsigned long long count = 0;
0090 for (f_.peek(); !f_.eof(); f_.peek()) {
0091 unsigned long long id = 0;
0092 std::streampos jump(0);
0093 read_pod(f_, &jump);
0094 if (f_.fail() || jump == zeropos)
0095 return count;
0096 f_.seekp(jump);
0097 if (f_.fail())
0098 return count;
0099 const CatalogEntry *entry = CatalogEntry::read(*catalogEntryClassId(), *itemLocationClassId(), f_);
0100 if (entry) {
0101 id =
0102 cat_.makeEntry(*entry, entry->compressionCode(), entry->itemLength(), entry->location(), entry->offset());
0103 delete entry;
0104 }
0105 if (!id)
0106 return count;
0107 ++count;
0108 }
0109 return count;
0110 }
0111
0112 inline void writeCatalog(const std::vector<std::string> &annotations) {
0113 const std::string &catFile = catalogFileName();
0114 ofstream cats(catFile.c_str());
0115 if (!cats) {
0116 std::ostringstream os;
0117 os << "In CatalogRecovery::writeCatalog: "
0118 << "failed to open catalog data file \"" << catFile << '"';
0119 throw IOOpeningFailure(os.str());
0120 }
0121
0122 const unsigned compress = static_cast<unsigned>(compressionMode());
0123 if (!writeBinaryCatalog(cats, compress, 1, annotations, cat_)) {
0124 std::ostringstream os;
0125 os << "In CatalogRecovery::writeCatalog: "
0126 << "failed to write catalog data to file " << catFile;
0127 throw IOWriteFailure(os.str());
0128 }
0129 }
0130
0131 inline void flush() {}
0132 };
0133 }
0134
0135 int main(int argc, char const *argv[]) {
0136 CmdLine cmdline(argc, argv);
0137
0138 if (argc == 1) {
0139 print_usage(cmdline.progname());
0140 return 0;
0141 }
0142
0143 std::string archiveName;
0144 std::vector<std::string> annotations;
0145 try {
0146 cmdline.optend();
0147
0148 const unsigned cmdargc = cmdline.argc();
0149 if (cmdargc != 1 && cmdargc != 2)
0150 throw CmdLineError("wrong number of command line arguments");
0151 cmdline >> archiveName;
0152 if (cmdargc > 1) {
0153 annotations.resize(1);
0154 cmdline >> annotations[0];
0155 }
0156 } catch (CmdLineError &e) {
0157 cerr << "Error in " << cmdline.progname() << ": " << e.str() << endl;
0158 print_usage(cmdline.progname());
0159 return 1;
0160 }
0161
0162 CatalogRecovery recovery(archiveName.c_str());
0163
0164
0165 const std::string &catFile = recovery.catalogFileName();
0166 {
0167 ifstream cats(catFile.c_str());
0168 if (cats) {
0169 cout << "Catalog file \"" << catFile << "\" already exists" << endl;
0170 return 1;
0171 }
0172 }
0173
0174 unsigned long long itemCount = 0;
0175 unsigned long fileCount = 0;
0176 try {
0177 for (;; ++fileCount)
0178 itemCount += recovery.processFile(fileCount);
0179 } catch (IOOpeningFailure &e) {
0180 if (!fileCount) {
0181 cout << "Archive \"" << archiveName << "\" could not be open. " << e.what() << endl;
0182 return 1;
0183 }
0184 } catch (exception &e) {
0185 cout << "Error in data processing cycle. " << e.what() << endl;
0186 return 1;
0187 }
0188
0189 try {
0190 recovery.writeCatalog(annotations);
0191 } catch (exception &e) {
0192 cout << e.what() << endl;
0193 return 1;
0194 }
0195
0196 cout << "Wrote catalog file \"" << catFile << "\"\n"
0197 << "The catalog contains metadata for " << itemCount << " items found in " << fileCount << " data file"
0198 << (fileCount == 1UL ? "" : "s") << endl;
0199 return 0;
0200 }