Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 11:56:21

0001 // This is the catalog recovery program. For it to be successful, the
0002 // original archive must have been created using the "cat=s" option.
0003 
0004 #include <fstream>
0005 #include <iostream>
0006 
0007 #include "Alignment/Geners/interface/BinaryArchiveBase.hh"
0008 #include <memory>
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 /* id */,
0046                                           unsigned * /* compressionCode */,
0047                                           unsigned long long * /* length */) {
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 & /* record */,
0061                                            unsigned /* compressCode */,
0062                                            unsigned long long /* itemLength */) {
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 }  // namespace
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   // Check if the catalog file already exists. Do not overwrite.
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 }