CMS 3D CMS Logo

BinaryFileArchive.cc
Go to the documentation of this file.
1 #include <sstream>
2 
3 #include "Alignment/Geners/interface/BinaryFileArchive.hh"
4 
5 #include "Alignment/Geners/interface/ContiguousCatalog.hh"
6 #include "Alignment/Geners/interface/IOException.hh"
7 #include "Alignment/Geners/interface/WriteOnlyCatalog.hh"
8 #include "Alignment/Geners/interface/streamposIO.hh"
9 #include "Alignment/Geners/interface/uriUtils.hh"
10 
11 namespace gs {
12  BinaryFileArchive::BinaryFileArchive(const char *basename,
13  const char *mode,
14  const char *ann,
15  const unsigned dataFileBufferSize,
16  const unsigned catalogFileBufferSize)
17  : BinaryArchiveBase(basename, mode),
18  filebuf_(nullptr),
19  catabuf_(nullptr),
20  annotation_(ann ? std::string(ann) : std::string("")),
21  dataFileName_(AbsArchive::name() + ".0.gsbd"), // binary data
22  catalogFileName_(AbsArchive::name() + ".gsbmf"), // binary metafile
23  dataFileURI_(localFileURI(dataFileName_.c_str())),
24  lastpos_(0),
25  jumppos_(0),
26  catalogMergeLevel_(1),
27  annotationsMerged_(false),
28  streamFlushed_(true) {
29  if (!modeValid())
30  return;
31 
32  try {
33  // Get a new buffer for the data and open the data stream
34  if (dataFileBufferSize)
35  filebuf_ = new char[dataFileBufferSize];
36  dataStream_.rdbuf()->pubsetbuf(filebuf_, dataFileBufferSize);
37  openDataFile(dataStream_, dataFileName_.c_str());
38  dataStream_.seekp(0, std::ios_base::end);
39 
40  // Get a new buffer for the catalog and open the catalog stream.
41  // We may have to rewrite the complete catalog, so remove the flag
42  // std::ios_base::app from the opening mode.
43  if (catalogFileBufferSize)
44  catabuf_ = new char[catalogFileBufferSize];
45  catStream_.rdbuf()->pubsetbuf(catabuf_, catalogFileBufferSize);
46  catStream_.open(catalogFileName_.c_str(), openmode() & ~std::ios_base::app);
47  if (!catStream_.is_open())
48  throw IOOpeningFailure("gs::BinaryFileArchive constructor", catalogFileName_);
49 
50  // Can we use a write-only catalog?
51  if (openmode() & std::ios_base::in) {
52  // Reading is allowed. Have to use in-memory catalog.
53  // If the file data already exists, get the catalog in.
54  if (isEmptyFile(catStream_))
55  setCatalog(new ContiguousCatalog());
56  else
57  readCatalog<ContiguousCatalog>();
58  } else {
59  // Yes, we can use a write-only catalog.
60  // Is the catalog file empty? If so, write out
61  // the stuff needed at the beginning of the file.
62  // If not, assume that the necessary stuff is
63  // already there. Note that in this case we will
64  // not be able to add the annotation.
65  if (isEmptyFile(catStream_)) {
66  setCatalog(new WriteOnlyCatalog(catStream_));
67  writeCatalog();
68  } else {
69  // Have to read in the catalog contents
70  catStream_.close();
71  catStream_.clear();
72  catStream_.open(catalogFileName_.c_str(), openmode() | std::ios_base::in);
73  if (!catStream_.is_open())
74  throw IOOpeningFailure("gs::BinaryFileArchive constructor", catalogFileName_);
75  readCatalog<WriteOnlyCatalog>();
76  catStream_.seekp(0, std::ios_base::end);
77  }
78  }
79  } catch (std::exception &e) {
80  setCatalog(nullptr);
81  releaseBuffers();
82  errorStream() << e.what();
83  }
84  }
85 
86  void BinaryFileArchive::releaseBuffers() {
87  if (dataStream_.is_open())
88  dataStream_.close();
89  if (catStream_.is_open())
90  catStream_.close();
91  catStream_.rdbuf()->pubsetbuf(nullptr, 0);
92  dataStream_.rdbuf()->pubsetbuf(nullptr, 0);
93  delete[] catabuf_;
94  catabuf_ = nullptr;
95  delete[] filebuf_;
96  filebuf_ = nullptr;
97  }
98 
99  BinaryFileArchive::~BinaryFileArchive() {
100  flush();
101  releaseBuffers();
102  }
103 
104  void BinaryFileArchive::writeCatalog() {
105  if (isOpen()) {
106  if (!annotationsMerged_) {
107  if (!annotation_.empty())
108  catalogAnnotations_.push_back(annotation_);
109  annotationsMerged_ = true;
110  }
111  const unsigned compress = static_cast<unsigned>(compressionMode());
112  if (!writeBinaryCatalog(catStream_, compress, catalogMergeLevel_, catalogAnnotations_, *catalog())) {
113  std::ostringstream os;
114  os << "In BinaryFileArchive::writeCatalog: "
115  << "failed to write catalog data to file " << catalogFileName_;
116  throw IOWriteFailure(os.str());
117  }
118  }
119  }
120 
121  std::istream &BinaryFileArchive::plainInputStream(const unsigned long long id,
122  unsigned *compressionCode,
123  unsigned long long *length) {
124  if (isOpen()) {
125  assert(openmode() & std::ios_base::in);
126  if (!id)
127  throw gs::IOInvalidArgument("In gs::BinaryFileArchive::plainInputStream: invalid item id");
128  std::streampos pos;
129  if (!catalog()->retrieveStreampos(id, compressionCode, length, &pos)) {
130  std::ostringstream os;
131  os << "In gs::BinaryFileArchive::plainInputStream: "
132  << "failed to locate item with id " << id << "in the catalog stored in file " << catalogFileName_;
133  throw gs::IOInvalidArgument(os.str());
134  }
135  if (!streamFlushed_) {
136  dataStream_.flush();
137  streamFlushed_ = true;
138  }
139  dataStream_.seekg(pos);
140  }
141  return dataStream_;
142  }
143 
144  unsigned long long BinaryFileArchive::addToCatalog(const AbsRecord &record,
145  const unsigned compressionCode,
146  const unsigned long long itemLength) {
147  unsigned long long id = 0;
148  if (isOpen()) {
149  id = catalog()->makeEntry(record, compressionCode, itemLength, ItemLocation(lastpos_, dataFileURI_.c_str()));
150  if (id && injectMetadata()) {
151  const CatalogEntry *entry = catalog()->lastEntryMade();
152  assert(entry);
153  dataStream_.seekp(0, std::ios_base::end);
154  std::streampos now = dataStream_.tellp();
155  if (entry->write(dataStream_)) {
156  dataStream_.seekp(jumppos_);
157  write_pod(dataStream_, now);
158  dataStream_.seekp(0, std::ios_base::end);
159  } else
160  id = 0;
161  }
162  }
163  return id;
164  }
165 
166  std::ostream &BinaryFileArchive::plainOutputStream() {
167  if (isOpen()) {
168  assert(openmode() & std::ios_base::out);
169  dataStream_.seekp(0, std::ios_base::end);
170  if (injectMetadata()) {
171  jumppos_ = dataStream_.tellp();
172  std::streampos catpos(0);
173  write_pod(dataStream_, catpos);
174  }
175  lastpos_ = dataStream_.tellp();
176  streamFlushed_ = false;
177  }
178  return dataStream_;
179  }
180 
181  void BinaryFileArchive::flush() {
182  if (isOpen()) {
183  if (!streamFlushed_) {
184  dataStream_.flush();
185  streamFlushed_ = true;
186  }
187 
188  if (openmode() & std::ios_base::out) {
189  if (dynamic_cast<WriteOnlyCatalog *>(catalog()) == nullptr)
190  writeCatalog();
191  catStream_.flush();
192  }
193  }
194  }
195 } // namespace gs
assert(be >=bs)
bool writeBinaryCatalog(std::ostream &os, const unsigned compressionCode, const unsigned mergeLevel, const std::vector< std::string > &annotations, const AbsCatalog &catalog, const unsigned formatId)
Definition: CatalogIO.cc:4
std::string localFileURI(const char *filename)
Definition: uriUtils.cc:8
Definition: AbsArchive.cc:46