CMS 3D CMS Logo

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