CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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/uriUtils.hh"
6 #include "Alignment/Geners/interface/ContiguousCatalog.hh"
7 #include "Alignment/Geners/interface/WriteOnlyCatalog.hh"
8 #include "Alignment/Geners/interface/IOException.hh"
9 #include "Alignment/Geners/interface/streamposIO.hh"
10 
11 namespace gs {
12  BinaryFileArchive::BinaryFileArchive(const char* basename,
13  const char* mode, const char* ann,
14  const unsigned dataFileBufferSize,
15  const unsigned catalogFileBufferSize)
16  : BinaryArchiveBase(basename, mode),
17  filebuf_(0),
18  catabuf_(0),
19  annotation_(ann ? std::string(ann) : std::string("")),
20  dataFileName_(AbsArchive::name() + ".0.gsbd"), // binary data
21  catalogFileName_(AbsArchive::name() + ".gsbmf"), // binary metafile
22  dataFileURI_(localFileURI(dataFileName_.c_str())),
23  lastpos_(0),
24  jumppos_(0),
25  catalogMergeLevel_(1),
26  annotationsMerged_(false),
27  streamFlushed_(true)
28  {
29  if (!modeValid()) return;
30 
31  try
32  {
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(),
47  openmode() & ~std::ios_base::app);
48  if (!catStream_.is_open())
49  throw IOOpeningFailure("gs::BinaryFileArchive constructor",
50  catalogFileName_);
51 
52  // Can we use a write-only catalog?
53  if (openmode() & std::ios_base::in)
54  {
55  // Reading is allowed. Have to use in-memory catalog.
56  // If the file data already exists, get the catalog in.
57  if (isEmptyFile(catStream_))
58  setCatalog(new ContiguousCatalog());
59  else
60  readCatalog<ContiguousCatalog>();
61  }
62  else
63  {
64  // Yes, we can use a write-only catalog.
65  // Is the catalog file empty? If so, write out
66  // the stuff needed at the beginning of the file.
67  // If not, assume that the necessary stuff is
68  // already there. Note that in this case we will
69  // not be able to add the annotation.
70  if (isEmptyFile(catStream_))
71  {
72  setCatalog(new WriteOnlyCatalog(catStream_));
73  writeCatalog();
74  }
75  else
76  {
77  // Have to read in the catalog contents
78  catStream_.close();
79  catStream_.clear();
80  catStream_.open(catalogFileName_.c_str(),
81  openmode() | std::ios_base::in);
82  if (!catStream_.is_open()) throw IOOpeningFailure(
83  "gs::BinaryFileArchive constructor", catalogFileName_);
84  readCatalog<WriteOnlyCatalog>();
85  catStream_.seekp(0, std::ios_base::end);
86  }
87  }
88  }
89  catch (std::exception& e)
90  {
91  setCatalog(0);
92  releaseBuffers();
93  errorStream() << e.what();
94  }
95  }
96 
97  void BinaryFileArchive::releaseBuffers()
98  {
99  if (dataStream_.is_open()) dataStream_.close();
100  if (catStream_.is_open()) catStream_.close();
101  catStream_.rdbuf()->pubsetbuf(0, 0);
102  dataStream_.rdbuf()->pubsetbuf(0, 0);
103  delete [] catabuf_; catabuf_ = 0;
104  delete [] filebuf_; filebuf_ = 0;
105  }
106 
107  BinaryFileArchive::~BinaryFileArchive()
108  {
109  flush();
110  releaseBuffers();
111  }
112 
113  void BinaryFileArchive::writeCatalog()
114  {
115  if (isOpen())
116  {
117  if (!annotationsMerged_)
118  {
119  if (annotation_.size())
120  catalogAnnotations_.push_back(annotation_);
121  annotationsMerged_ = true;
122  }
123  const unsigned compress = static_cast<unsigned>(compressionMode());
124  if (!writeBinaryCatalog(catStream_, compress, catalogMergeLevel_,
125  catalogAnnotations_, *catalog()))
126  {
127  std::ostringstream os;
128  os << "In BinaryFileArchive::writeCatalog: "
129  << "failed to write catalog data to file "
130  << catalogFileName_;
131  throw IOWriteFailure(os.str());
132  }
133  }
134  }
135 
136  std::istream& BinaryFileArchive::plainInputStream(
137  const unsigned long long id,
138  unsigned* compressionCode,
139  unsigned long long* length)
140  {
141  if (isOpen())
142  {
143  assert(openmode() & std::ios_base::in);
144  if (!id) throw gs::IOInvalidArgument(
145  "In gs::BinaryFileArchive::plainInputStream: invalid item id");
146  std::streampos pos;
147  if (!catalog()->retrieveStreampos(
148  id, compressionCode, length, &pos))
149  {
150  std::ostringstream os;
151  os << "In gs::BinaryFileArchive::plainInputStream: "
152  << "failed to locate item with id " << id
153  << "in the catalog stored in file " << catalogFileName_;
154  throw gs::IOInvalidArgument(os.str());
155  }
156  if (!streamFlushed_)
157  {
158  dataStream_.flush();
159  streamFlushed_ = true;
160  }
161  dataStream_.seekg(pos);
162  }
163  return dataStream_;
164  }
165 
166  unsigned long long BinaryFileArchive::addToCatalog(
167  const AbsRecord& record, const unsigned compressionCode,
168  const unsigned long long itemLength)
169  {
170  unsigned long long id = 0;
171  if (isOpen())
172  {
173  id = catalog()->makeEntry(
174  record, compressionCode, itemLength,
175  ItemLocation(lastpos_, dataFileURI_.c_str()));
176  if (id && injectMetadata())
177  {
178  const CatalogEntry* entry = catalog()->lastEntryMade();
179  assert(entry);
180  dataStream_.seekp(0, std::ios_base::end);
181  std::streampos now = dataStream_.tellp();
182  if (entry->write(dataStream_))
183  {
184  dataStream_.seekp(jumppos_);
185  write_pod(dataStream_, now);
186  dataStream_.seekp(0, std::ios_base::end);
187  }
188  else
189  id = 0;
190  }
191  }
192  return id;
193  }
194 
195  std::ostream& BinaryFileArchive::plainOutputStream()
196  {
197  if (isOpen())
198  {
199  assert(openmode() & std::ios_base::out);
200  dataStream_.seekp(0, std::ios_base::end);
201  if (injectMetadata())
202  {
203  jumppos_ = dataStream_.tellp();
204  std::streampos catpos(0);
205  write_pod(dataStream_, catpos);
206  }
207  lastpos_ = dataStream_.tellp();
208  streamFlushed_ = false;
209  }
210  return dataStream_;
211  }
212 
213  void BinaryFileArchive::flush()
214  {
215  if (isOpen())
216  {
217  if (!streamFlushed_)
218  {
219  dataStream_.flush();
220  streamFlushed_ = true;
221  }
222 
223  if (openmode() & std::ios_base::out)
224  {
225  if (dynamic_cast<WriteOnlyCatalog*>(catalog()) == 0)
226  writeCatalog();
227  catStream_.flush();
228  }
229  }
230  }
231 }
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
#define end
Definition: vmac.h:37
tuple out
Definition: dbtoconf.py:99
volatile std::atomic< bool > shutdown_flag false