CMS 3D CMS Logo

AbsArchive.cc
Go to the documentation of this file.
1 #include <cassert>
2 #include <sstream>
3 
4 #include "Alignment/Geners/interface/AbsArchive.hh"
5 #include "Alignment/Geners/interface/IOException.hh"
6 
7 #define GS_STREAM_COPY_BUFFER_SIZE 65536
8 
9 static void archive_stream_copy(std::istream &in, std::size_t count, std::ostream &out) {
10  if (count) {
11  const std::size_t bufsize = GS_STREAM_COPY_BUFFER_SIZE;
12  char buffer[bufsize];
13 
14  bool in_fail = in.fail();
15  bool out_fail = out.fail();
16  while (count > bufsize && !in_fail && !out_fail) {
17  in.read(buffer, bufsize);
18  in_fail = in.fail();
19  if (!in_fail) {
20  out.write(buffer, bufsize);
21  out_fail = out.fail();
22  }
23  count -= bufsize;
24  }
25  if (!in_fail && !out_fail) {
26  in.read(buffer, count);
27  if (!in.fail())
28  out.write(buffer, count);
29  }
30  }
31 }
32 
33 namespace {
34  class NotWritableRecord : public gs::AbsRecord {
35  public:
36  inline NotWritableRecord(const gs::ClassId &classId, const char *ioPrototype, const char *name, const char *category)
37  : gs::AbsRecord(classId, ioPrototype, name, category) {}
38 
39  private:
40  NotWritableRecord() = delete;
41  inline bool writeData(std::ostream &) const override { return false; }
42  };
43 } // namespace
44 
45 namespace gs {
46  AbsArchive::AbsArchive(const char *name) : name_(name ? name : ""), lastItemId_(0), lastItemLength_(0) {}
47 
48  void AbsArchive::addItemToReference(AbsReference &r, const unsigned long long id) const { r.addItemId(id); }
49 
50  unsigned long long AbsArchive::copyItem(const unsigned long long id,
51  AbsArchive *destination,
52  const char *newName,
53  const char *newCategory) {
54  if (!isReadable())
55  throw gs::IOInvalidArgument(
56  "In gs::AbsArchive::copyItem: "
57  "origin archive is not readable");
58  assert(destination);
59  if (this == destination)
60  throw gs::IOInvalidArgument(
61  "In gs::AbsArchive::copyItem: "
62  "origin and destination archives are the same");
63  AbsArchive &ar(*destination);
64  if (!ar.isWritable())
65  throw gs::IOInvalidArgument(
66  "In gs::AbsArchive::copyItem: "
67  "destination archive is not writable");
68  CPP11_shared_ptr<const CatalogEntry> entry(catalogEntry(id));
69  if (!entry)
70  throw gs::IOInvalidArgument(
71  "In gs::AbsArchive::copyItem: no item "
72  "in the archive with the given id");
73 
74  // Position the input stream
75  long long sz = 0;
76  std::istream &is = inputStream(id, &sz);
77 
78  // The following code is similar to the one in the "operator<<"
79  // below w.r.t. operations with the output archive
80  std::ostream &os = ar.outputStream();
81  std::streampos base = os.tellp();
82  std::ostream &compressed = ar.compressedStream(os);
83 
84  // Transfer the data between the streams
85  unsigned long long len;
86  if (sz >= 0)
87  len = sz;
88  else
89  len = entry->itemLength();
90  archive_stream_copy(is, len, compressed);
91  if (is.fail())
92  throw IOReadFailure(
93  "In gs::AbsArchive::copyItem: "
94  "input stream failure");
95  if (compressed.fail())
96  throw IOWriteFailure(
97  "In gs::AbsArchive::copyItem: "
98  "output stream failure");
99  const unsigned compressCode = ar.flushCompressedRecord(compressed);
100  if (os.fail())
101  throw IOWriteFailure(
102  "In gs::AbsArchive::copyItem: "
103  "failed to transfer compressed data");
104 
105  // Figure out the record length. Naturally, can't have negative length.
106  std::streamoff off = os.tellp() - base;
107  const long long delta = off;
108  assert(delta >= 0LL);
109 
110  // We need to create a record out of the catalog entry we have found
111  const char *name = newName;
112  if (!name)
113  name = entry->name().c_str();
114  const char *category = newCategory;
115  if (!category)
116  category = entry->category().c_str();
117  NotWritableRecord record(entry->type(), entry->ioPrototype().c_str(), name, category);
118 
119  // Add the record to the catalog
120  const unsigned long long id2 = ar.addToCatalog(record, compressCode, delta);
121  if (id == 0ULL)
122  throw IOWriteFailure(
123  "In gs::AbsArchive::copyItem: "
124  "failed to add catalog entry");
125  ar.lastItemId_ = id2;
126  ar.lastItemLength_ = delta;
127  return id2;
128  }
129 } // namespace gs
130 
131 static std::string local_error_message(gs::AbsArchive &ar, const gs::AbsRecord &record, const char *failedAction) {
132  std::ostringstream err;
133  err << "In operator<<(gs::AbsArchive& ar, const gs::AbsRecord& record): "
134  << "failed to " << failedAction << " to the archive \"" << ar.name() << "\" for item with type \""
135  << record.type().name() << "\", name \"" << record.name() << "\", and category \"" << record.category() << '"';
136  return err.str();
137 }
138 
139 gs::AbsArchive &operator<<(gs::AbsArchive &ar, const gs::AbsRecord &record) {
140  // Do not reuse records
141  if (record.id())
142  throw gs::IOInvalidArgument(
143  "In operator<<(gs::AbsArchive& ar, const gs::AbsRecord& record): "
144  "records can not be reused");
145 
146  // Get the relevant streams. Do not change the order
147  // of the next three lines, some code which does
148  // not implement compression may actually rely on
149  // the fact that the "outputStream()" method
150  // is called before "compressedStream()".
151  std::ostream &os = ar.outputStream();
152  std::streampos base = os.tellp();
153  std::ostream &compressed = ar.compressedStream(os);
154 
155  // Write the data
156  if (!record.writeData(compressed))
157  throw gs::IOWriteFailure(local_error_message(ar, record, "write data"));
158 
159  const unsigned compressCode = ar.flushCompressedRecord(compressed);
160  if (os.fail())
161  throw gs::IOWriteFailure(local_error_message(ar, record, "transfer compressed data"));
162 
163  // Figure out the record length. Naturally, can't have negative length.
164  std::streamoff off = os.tellp() - base;
165  const long long delta = off;
166  assert(delta >= 0LL);
167 
168  // Add the record to the catalog
169  const unsigned long long id = ar.addToCatalog(record, compressCode, delta);
170  if (id == 0ULL)
171  throw gs::IOWriteFailure(local_error_message(ar, record, "add catalog entry"));
172 
173  // Mark record as written and give feedback about item length
174  record.itemId_ = id;
175  record.itemLength_ = delta;
176 
177  // Same thing for the archive
178  ar.lastItemId_ = id;
179  ar.lastItemLength_ = delta;
180 
181  return ar;
182 }
dbl * delta
Definition: mlp_gen.cc:36
static void archive_stream_copy(std::istream &in, std::size_t count, std::ostream &out)
Definition: AbsArchive.cc:9
JetCorrectorParameters::Record record
Definition: classes.h:7
#define GS_STREAM_COPY_BUFFER_SIZE
Definition: AbsArchive.cc:7
string newName
Definition: mps_merge.py:86
gs::AbsArchive & operator<<(gs::AbsArchive &ar, const gs::AbsRecord &record)
Definition: AbsArchive.cc:139
base
Make Sure CMSSW is Setup ##.
static std::string local_error_message(gs::AbsArchive &ar, const gs::AbsRecord &record, const char *failedAction)
Definition: AbsArchive.cc:131
Definition: AbsArchive.cc:45