Line data Source code
1 : #include <alma/ASDMBinaries/SDMDataObjectReader.h>
2 :
3 : #include <iostream>
4 : #include <iomanip>
5 : #include <unistd.h>
6 : #include <sys/types.h>
7 : #include <sys/mman.h>
8 : #include <fcntl.h>
9 : #include <sys/stat.h>
10 : #include <errno.h>
11 : #include <exception>
12 : #include <sstream>
13 :
14 : #include <alma/ASDMBinaries/CommonDefines.h>
15 :
16 : #if defined( __APPLE__ )
17 : #include <AvailabilityMacros.h>
18 : // 10.5 defines stat64 but Tiger does NOT
19 : #if defined(MAC_OS_X_VERSION_10_4) && ! defined(MAC_OS_X_VERSION_10_5)
20 : #define stat64 stat
21 : #define fstat64 fstat
22 : #endif
23 : #endif
24 :
25 : using namespace CorrelationModeMod;
26 : using namespace CorrelatorTypeMod;
27 : using namespace PrimitiveDataTypeMod;
28 : using namespace ProcessorTypeMod;
29 :
30 : using namespace std;
31 :
32 : namespace asdmbinaries {
33 :
34 : const string SDMDataObjectReader::MIMEBOUNDARY_1 = $MIMEBOUNDARY1;
35 : const string SDMDataObjectReader::MIMEBOUNDARY_2 = $MIMEBOUNDARY2;
36 :
37 : #ifndef WITHOUT_BOOST
38 : const boost::regex SDMDataObjectReader::CONTENTIDBINREGEXP(" <([a-zA-Z]+)_([_0-9]+)\\.bin>");
39 : const boost::regex SDMDataObjectReader::CONTENTIDBINREGEXP1(" <([a-zA-Z]+)_([0-9]+)\\.bin>");
40 : const boost::regex SDMDataObjectReader::CONTENTIDBINREGEXP2(" <([a-zA-Z]+)_([0-9]+)_([0-9]+)\\.bin>");
41 : // const boost::regex SDMDataObjectReader::CONTENTIDSUBSETREGEXP(" <(Subset)_([0-9]+)\\.xml>");
42 : const boost::regex SDMDataObjectReader::CONTENTIDSUBSETREGEXP(" <(Subset)_([0-9]+)(_[0-9]+)?\\.xml>");
43 : const boost::regex SDMDataObjectReader::CONTENTIDDATASTRUCTUREREGEXP(" <DataStructure.xml>");
44 : #else
45 : const std::regex SDMDataObjectReader::CONTENTIDBINREGEXP(" <([a-zA-Z]+)_([_0-9]+)\\.bin>");
46 : const std::regex SDMDataObjectReader::CONTENTIDBINREGEXP1(" <([a-zA-Z]+)_([0-9]+)\\.bin>");
47 : const std::regex SDMDataObjectReader::CONTENTIDBINREGEXP2(" <([a-zA-Z]+)_([0-9]+)_([0-9]+)\\.bin>");
48 : // const std::regex SDMDataObjectReader::CONTENTIDSUBSETREGEXP(" <(Subset)_([0-9]+)\\.xml>");
49 : const std::regex SDMDataObjectReader::CONTENTIDSUBSETREGEXP(" <(Subset)_([0-9]+)(_[0-9]+)?\\.xml>");
50 : const std::regex SDMDataObjectReader::CONTENTIDDATASTRUCTUREREGEXP(" <DataStructure.xml>");
51 : #endif
52 : set<string> SDMDataObjectReader::BINATTACHNAMES;
53 : map<string, SDMDataObjectReader::BINATTACHCODES> SDMDataObjectReader::name2code;
54 : const bool SDMDataObjectReader::initClass_ = SDMDataObjectReader::initClass();
55 :
56 : // SDMDataObjectReader:: methods
57 : //
58 0 : SDMDataObjectReader::SDMDataObjectReader() {
59 0 : init();
60 0 : }
61 :
62 0 : SDMDataObjectReader::~SDMDataObjectReader() {
63 0 : done();
64 0 : }
65 :
66 3 : bool SDMDataObjectReader::initClass() {
67 3 : char* binAttachNamesC[] = {(char *) "actualDurations", (char *) "actualTimes", (char *) "autoData", (char *) "flags", (char *) "crossData", (char *) "zeroLags", 0};
68 21 : for (int i = 0; binAttachNamesC[i]; i++) {
69 18 : BINATTACHNAMES.insert(string(binAttachNamesC[i]));
70 : }
71 :
72 3 : name2code["actualDurations"] = ACTUALDURATIONS;
73 3 : name2code["actualTimes"] = ACTUALTIMES;
74 3 : name2code["autoData"] = AUTODATA;
75 3 : name2code["flags"] = FLAGS;
76 3 : name2code["crossData"] = CROSSDATA;
77 3 : name2code["zeroLags"] = ZEROLAGS;
78 :
79 3 : return true;
80 : }
81 :
82 0 : void SDMDataObjectReader::init() {
83 0 : filedes_ = 0;
84 0 : data_ = (char *) 0;
85 0 : position_ = 0;
86 0 : lastPosition_ = 0;
87 0 : endPosition_ = 0;
88 :
89 0 : read_ = UNKNOWN_;
90 :
91 0 : integrationNum_ = 0;
92 0 : }
93 :
94 0 : string::size_type SDMDataObjectReader::find(const string& s) {
95 :
96 : while (true) {
97 0 : while ((position_ < endPosition_) && (data_[position_++] != s.at(0))) {;}
98 :
99 0 : if (position_ == endPosition_) return string::npos;
100 :
101 0 : string::size_type lastPosition_ = position_;
102 0 : unsigned long long int i = 1;
103 :
104 0 : while ((position_ < endPosition_) && (i < s.length())) {
105 0 : if (s.at(i) != data_[position_]) break;
106 0 : i++;
107 0 : position_++;
108 : }
109 :
110 0 : if (i == s.length()) return (position_ - s.length());
111 :
112 0 : if (position_ == endPosition_) return string::npos;
113 :
114 0 : position_ = lastPosition_; //+1;
115 0 : }
116 : }
117 :
118 0 : bool SDMDataObjectReader::compare(const string& s) {
119 0 : string::size_type index = position_;
120 :
121 0 : unsigned int i = 0;
122 0 : while ((index < endPosition_) && (i < s.length()) && (s.at(i++) == data_[index++])) {
123 : ;
124 : }
125 0 : return (i == s.length());
126 : }
127 :
128 0 : bool SDMDataObjectReader::EOD() {
129 0 : return position_ >= endPosition_;
130 : }
131 :
132 :
133 0 : string SDMDataObjectReader::extractXMLHeader(const string& boundary) {
134 : // cout << "Entering extractXMLHeader" << endl;
135 :
136 0 : string boundary_ = "\n--"+boundary;
137 :
138 0 : unsigned long int positionBeg = 0;
139 0 : unsigned long int positionEnd = 0;
140 :
141 : // We assume that we are at the first character of the body.
142 0 : positionBeg = position_;
143 :
144 : // Look for the next boundary supposed to be found right after an the XML header.
145 0 : if ( (positionEnd = find(boundary_)) == string::npos) {
146 0 : ostringstream eos;
147 0 : eos << "A second MIME boundary '" << boundary <<"' could not be found in the MIME message after position " << positionBeg << ".";
148 0 : throw SDMDataObjectReaderException(eos.str());
149 0 : }
150 :
151 0 : string xmlPart = string(data_+positionBeg, positionEnd-positionBeg);
152 :
153 : // cout << "Found XML Header : " << xmlPart << endl;
154 : // cout << "Exiting extractXMLHeader" << endl;
155 :
156 0 : return xmlPart;
157 0 : }
158 :
159 :
160 0 : void SDMDataObjectReader::tokenize(const string& str,
161 : vector<string>& tokens,
162 : const string& delimiters) {
163 : // Skip delimiters at beginning.
164 0 : string::size_type lastPos = str.find_first_not_of(delimiters, 0);
165 : // Find first "non-delimiter".
166 0 : string::size_type pos = str.find_first_of(delimiters, lastPos);
167 :
168 0 : while (string::npos != pos || string::npos != lastPos) {
169 : // Found a token, add it to the vector.
170 0 : tokens.push_back(str.substr(lastPos, pos - lastPos));
171 : // Skip delimiters. Note the "not_of"
172 0 : lastPos = str.find_first_not_of(delimiters, pos);
173 : // Find next "non-delimiter"
174 0 : pos = str.find_first_of(delimiters, lastPos);
175 : }
176 0 : }
177 :
178 :
179 0 : void SDMDataObjectReader::getFields(const string& header, map<string, string>& fields) {
180 : // We are at the last character of the line preceding the 1st field declaration.
181 0 : istringstream iss;
182 0 : iss.str(header);
183 0 : string line;
184 :
185 0 : getline(iss, line); // skip an nl
186 :
187 : // Split each line into field-name, field-value
188 0 : while (getline(iss, line)) {
189 0 : vector<string> nv;
190 0 : tokenize(line, nv, ":");
191 0 : if (nv.size() < 2) {
192 0 : ostringstream oss;
193 0 : oss << "Invalid field in a MIME header '" << header << "', integration #" << integrationNum_;
194 0 : throw SDMDataObjectReaderException (oss.str());
195 0 : }
196 0 : fields[nv.at(0)] = nv.at(1);
197 0 : }
198 0 : }
199 :
200 0 : string SDMDataObjectReader::getContentID() {
201 : // We are at the beginning of an attachment right after its opening boundary.
202 0 : string::size_type lastPosition = position_;
203 :
204 : // Now let's extract the header (which is followed by two successive nl nl)
205 : string::size_type endHeader;
206 0 : if ( (endHeader = find ("\n\n")) == string::npos) {
207 0 : throw SDMDataObjectReaderException("Could not find the end of a MIME header");
208 : }
209 :
210 0 : string header(data_+lastPosition, (endHeader - lastPosition));
211 :
212 0 : map<string, string> fields;
213 0 : getFields(header, fields);
214 :
215 : // Look for the Content-ID field
216 0 : map<string, string>::iterator iter = fields.find("Content-ID");
217 0 : if (iter == fields.end()) {
218 0 : ostringstream oss;
219 0 : oss << "'Content-ID' field is missing the MIME header of an attachment (approx. char position = " << position_ << ").";
220 0 : throw SDMDataObjectReaderException(oss.str());
221 0 : }
222 0 : return iter->second;
223 0 : }
224 :
225 0 : string SDMDataObjectReader::getContentLocation() {
226 : // We are at the beginning of an attachment right after its opening boundary.
227 0 : string::size_type lastPosition = position_;
228 :
229 : // Now let's extract the header (which is followed by two successive nl nl)
230 : string::size_type endHeader;
231 0 : if ( (endHeader = find ("\n\n")) == string::npos) {
232 0 : throw SDMDataObjectReaderException("Could not find the end of a MIME header");
233 : }
234 :
235 0 : string header(data_+lastPosition, (endHeader - lastPosition));
236 :
237 0 : map<string, string> fields;
238 0 : getFields(header, fields);
239 :
240 : // Look for the Content-Location field
241 0 : map<string, string>::iterator iter = fields.find("Content-Location");
242 0 : if (iter == fields.end()) {
243 0 : ostringstream oss;
244 0 : oss << "'Content-Location' field is missing the MIME header of an attachment (approx. char position = " << position_ << ").";
245 0 : throw SDMDataObjectReaderException(oss.str());
246 0 : }
247 0 : return iter->second;
248 0 : }
249 :
250 0 : void SDMDataObjectReader::processBinaryAttachment(const string& boundary, const SDMDataSubset& sdmDataSubset) {
251 :
252 0 : string contentLocation = getContentLocation();
253 :
254 : // Extract the attachment name and the integration number.
255 : #ifndef WITHOUT_BOOST
256 : boost::cmatch what;
257 : boost::regex r(" *" + sdmDataSubset.projectPath()+"(actualDurations|actualTimes|autoData|flags|crossData|zeroLags)\\.bin");
258 : if (boost::regex_match(contentLocation.c_str(), what, r)) {
259 : }
260 : #else
261 0 : std::cmatch what;
262 0 : std::regex r(" *" + sdmDataSubset.projectPath()+"(actualDurations|actualTimes|autoData|flags|crossData|zeroLags)\\.bin");
263 0 : if (std::regex_match(contentLocation.c_str(), what, r)) {
264 : }
265 : #endif
266 : else {
267 0 : ostringstream oss;
268 0 : oss << "Invalid Content-Location field '" << contentLocation <<"' in MIME header of an attachment (approx. char position = " << position_ << ").";
269 0 : throw SDMDataObjectReaderException(oss.str());
270 0 : }
271 :
272 : // We are at the first byte of the body of the binary attachment.
273 0 : string::size_type startAttachPosition = position_; // mcaillat
274 :
275 : // Now look for its closing boundary (or opening boundary of the next one if any).
276 0 : string boundary_ = "\n--"+boundary;
277 : string::size_type endAttachPosition;
278 0 : if ( (endAttachPosition = find(boundary_)) == string::npos) {
279 0 : ostringstream eos;
280 0 : eos << "A MIME boundary '" << boundary << "' terminating a binary attachment starting approx. at character " << startAttachPosition <<" could not be found.";
281 0 : throw SDMDataObjectReaderException(eos.str());
282 0 : }
283 :
284 : // Compute the length of the attachment.
285 0 : string::size_type length = endAttachPosition - startAttachPosition;
286 :
287 :
288 :
289 0 : switch (name2code[what[1]]) {
290 0 : case ACTUALDURATIONS:
291 0 : actualDurations_ = (ACTUALDURATIONSTYPE *) (data_ + startAttachPosition);
292 0 : nActualDurations_ = length / sizeof (ACTUALDURATIONSTYPE);
293 0 : attachmentFlags.set(ACTUALDURATIONS);
294 : //cout << "actualDurations =" << (unsigned long int) actualDurations_ << ", nActualDurations = " << nActualDurations_ << endl;
295 0 : break;
296 0 : case ACTUALTIMES:
297 0 : actualTimes_ = (ACTUALTIMESTYPE *) (data_ + startAttachPosition);
298 0 : nActualTimes_ = length / sizeof( ACTUALTIMESTYPE);
299 0 : attachmentFlags.set(ACTUALTIMES);
300 : //cout << "actualTimes =" << (unsigned long int) actualTimes_ << ", nActualTimes = " << nActualTimes_ << endl;
301 0 : break;
302 0 : case AUTODATA:
303 0 : autoData_ = (AUTODATATYPE *) (data_ + startAttachPosition);
304 0 : nAutoData_ = length / sizeof(AUTODATATYPE);
305 0 : attachmentFlags.set(AUTODATA);
306 : //cout << "autoData =" << (unsigned long int) autoData_ << ", nAutoData = " << nAutoData_ << endl;
307 0 : break;
308 0 : case FLAGS:
309 0 : flags_ = (const FLAGSTYPE *) (data_ + startAttachPosition);
310 0 : nFlags_ = length / sizeof(FLAGSTYPE);
311 0 : attachmentFlags.set(FLAGS);
312 : //cout << "flags =" << (unsigned long int) flags_ << ", nFlags = " << nFlags_ << endl;
313 0 : break;
314 0 : case CROSSDATA:
315 0 : shortCrossData_ = 0;
316 0 : longCrossData_ = 0;
317 0 : floatCrossData_ = 0;
318 0 : switch (sdmDataSubset.crossDataType()) {
319 0 : case INT16_TYPE:
320 0 : shortCrossData_ = (const SHORTCROSSDATATYPE*) (data_ + startAttachPosition);
321 0 : nCrossData_ = length / sizeof (SHORTCROSSDATATYPE);
322 : //cout << "shortCrossData = " << (unsigned long int) shortCrossData_ << ", nShortCrossData = " << nCrossData_ << endl;
323 0 : break;
324 :
325 0 : case INT32_TYPE:
326 0 : longCrossData_ = (const INTCROSSDATATYPE*) (data_ + startAttachPosition);
327 0 : nCrossData_ = length / sizeof (INTCROSSDATATYPE);
328 : //cout << "longCrossData = " << (unsigned long int) longCrossData_ << ", nLongCrossData = " << nCrossData_ << endl;
329 0 : break;
330 :
331 0 : case FLOAT32_TYPE:
332 0 : floatCrossData_ = (const FLOATCROSSDATATYPE*) (data_ + startAttachPosition);
333 0 : nCrossData_ = length / sizeof (FLOATCROSSDATATYPE);
334 0 : break;
335 :
336 0 : default:
337 0 : ostringstream eos;
338 0 : eos << "'" << CPrimitiveDataType::toString(sdmDataSubset.crossDataType())
339 0 : << "' is not a valid primitive data type for CROSSDATA";
340 0 : throw SDMDataObjectReaderException(eos.str());
341 : // cout << "Unrecognized type for cross data" << endl;
342 : }
343 0 : attachmentFlags.set(CROSSDATA);
344 0 : break;
345 0 : case ZEROLAGS:
346 0 : zeroLags_ = (ZEROLAGSTYPE *) (data_ + startAttachPosition);
347 0 : nZeroLags_ = length / sizeof(ZEROLAGSTYPE) ;
348 0 : attachmentFlags.set(ZEROLAGS);
349 : //cout << "zeroLags =" << (unsigned long int) zeroLags_ << ", nZeroLags = " << nZeroLags_ << endl;
350 0 : break;
351 :
352 0 : default:
353 : //cout << "Unrecognized code" << endl;
354 0 : break;
355 : }
356 : // cout << "found a binary attachment" << endl;
357 0 : }
358 :
359 0 : void SDMDataObjectReader::processMIMESDMDataHeader() {
360 : // cout << "Entering processMIMESDMDataHeader" << endl;
361 0 : string sdmDataHeader = extractXMLHeader(MIMEBOUNDARY_1);
362 0 : parser_.parseMemoryHeader(sdmDataHeader, sdmDataObject_);
363 : // cout << "Exiting processMIMESDMDataHeader" << endl;
364 0 : }
365 :
366 0 : void SDMDataObjectReader::processMIMESDMDataSubsetHeader(SDMDataSubset& sdmDataSubset) {
367 : // cout << "Entering processMIMESDMDataSubsetHeader" << endl;
368 0 : string sdmDataSubsetHeader = extractXMLHeader(MIMEBOUNDARY_2);
369 0 : if (sdmDataSubset.owner_->isCorrelation())
370 0 : parser_.parseMemoryCorrSubsetHeader(sdmDataSubsetHeader, sdmDataSubset);
371 : else
372 0 : parser_.parseMemoryTPSubsetHeader(sdmDataSubsetHeader, sdmDataSubset);
373 : // cout << "Exiting processMIMESDMDataSubsetHeader" << endl;
374 0 : }
375 :
376 0 : void SDMDataObjectReader::processMIMEIntegration() {
377 : // cout << "Entering processMIMEIntegration" << endl;
378 :
379 : // We are 1 character beyond the end of --<MIMEBOUNDARY_2>
380 0 : string contentLocation = getContentLocation();
381 :
382 : #ifndef WITHOUT_BOOST
383 : boost::regex r(" *" + sdmDataObject_.projectPath() + "([[:digit:]]+/){1,2}" + "desc.xml");;
384 : ostringstream oss;
385 :
386 : // Extract the Subset name and the integration [, subintegration] number.
387 : boost::cmatch what;
388 : if (!boost::regex_match(contentLocation.c_str(), what, r)) {
389 : ostringstream oss;
390 : oss << "Invalid Content-Location field '" << contentLocation <<"' in MIME header of a Subset (approx. char position = " << position_ << ").";
391 : throw SDMDataObjectReaderException(oss.str());
392 : }
393 : #else
394 0 : std::regex r(" *" + sdmDataObject_.projectPath() + "([[:digit:]]+/){1,2}" + "desc.xml");;
395 0 : ostringstream oss;
396 :
397 : // Extract the Subset name and the integration [, subintegration] number.
398 0 : std::cmatch what;
399 0 : if (!std::regex_match(contentLocation.c_str(), what, r)) {
400 0 : ostringstream oss;
401 0 : oss << "Invalid Content-Location field '" << contentLocation <<"' in MIME header of a Subset (approx. char position = " << position_ << ").";
402 0 : throw SDMDataObjectReaderException(oss.str());
403 0 : }
404 : #endif
405 :
406 0 : SDMDataSubset integration(&sdmDataObject_);
407 :
408 : // The SDMDataSubset header.
409 0 : processMIMESDMDataSubsetHeader(integration);
410 :
411 0 : if (integration.aborted_) {
412 : // The [sub]integration has been aborted. Just append its header, without trying to get binary attachment.
413 0 : sdmDataObject_.append(integration);
414 : }
415 : else {
416 : // This is regular [sub]integration, process its binary attachments.
417 0 : attachmentFlags.reset();
418 0 : while (!EOD() && !compare("--")) {
419 0 : processBinaryAttachment(MIMEBOUNDARY_2, integration);
420 : }
421 :
422 0 : if (EOD())
423 0 : throw SDMDataObjectReaderException("Unexpected end of data");
424 :
425 : // Now check if the binary attachments found are compatible with the correlation mode
426 : // and if their sizes are equal to what is announced in the global header.
427 :
428 0 : if (!attachmentFlags.test(ACTUALDURATIONS)) {
429 : // No actualdurations attachment found, ok then set everything to 0.
430 0 : integration.actualDurations_ = 0;
431 0 : integration.nActualDurations_ = 0;
432 : }
433 : else {
434 0 : if (nActualDurations_ != sdmDataObject_.dataStruct().actualDurations().size()) {
435 0 : ostringstream oss;
436 0 : oss << "Data subset '"<<contentLocation<<"': ";
437 0 : oss << "zize of 'actualDuration' attachment (" << nActualDurations_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().actualDurations().size() << ")";
438 0 : throw SDMDataObjectReaderException(oss.str());
439 0 : }
440 :
441 0 : integration.actualDurations_ = actualDurations_;
442 0 : integration.nActualDurations_ = nActualDurations_;
443 : }
444 :
445 0 : if (!attachmentFlags.test(ACTUALTIMES)) {
446 : // No actualtimes attachment found, ok then set everything to 0.
447 0 : integration.actualTimes_ = 0;
448 0 : integration.nActualTimes_ = 0;
449 : }
450 : else {
451 0 : if (nActualTimes_ != sdmDataObject_.dataStruct().actualTimes().size()) {
452 0 : ostringstream oss;
453 0 : oss << "Data subset '"<<contentLocation<<"': ";
454 0 : oss << "size of 'actualTimes' attachment (" << nActualTimes_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().actualTimes().size() << ")";
455 0 : throw SDMDataObjectReaderException(oss.str());
456 0 : }
457 0 : integration.actualTimes_ = actualTimes_;
458 0 : integration.nActualTimes_ = nActualTimes_;
459 : }
460 :
461 : // The flags are optional. They may be absent.
462 0 : if (!attachmentFlags.test(FLAGS)) {
463 : // No flags binary attachment found, ok then set everything to 0.
464 0 : integration.flags_ = 0;
465 0 : integration.nFlags_ = 0;
466 : }
467 : else {
468 : // flags found
469 : // Check size conformity
470 0 : if (nFlags_ != sdmDataObject_.dataStruct().flags().size()) {
471 0 : ostringstream oss;
472 0 : oss << "Data subset '"<<contentLocation<<"': ";
473 0 : oss << "size of 'flags' attachment (" << nFlags_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().flags().size() << ")";
474 0 : throw SDMDataObjectReaderException(oss.str());
475 0 : }
476 :
477 : // Set pointer and size
478 0 : integration.flags_ = flags_;
479 0 : integration.nFlags_ = nFlags_;
480 : }
481 :
482 :
483 : //
484 : // The presence of crossData and autoData depends on the correlation mode.
485 :
486 : // crossDataTypeSize is not currently used
487 : // unsigned int crossDataTypeSize;
488 0 : switch (sdmDataObject_.correlationMode()) {
489 0 : case CROSS_ONLY:
490 0 : if (!attachmentFlags.test(CROSSDATA)) {
491 0 : ostringstream oss;
492 0 : oss << "Data subset '"<<contentLocation<<"': ";
493 0 : oss << "a binary attachment 'crossData' was expected in integration #" << integrationNum_;
494 0 : throw SDMDataObjectReaderException(oss.str());
495 0 : }
496 :
497 :
498 0 : if (nCrossData_ != sdmDataObject_.dataStruct().crossData().size()) {
499 0 : ostringstream oss;
500 0 : oss << "Data subset '"<<contentLocation<<"': ";
501 0 : oss << "size of 'crossData' attachment (" << nCrossData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().crossData().size() << ")";
502 0 : throw SDMDataObjectReaderException(oss.str());
503 0 : }
504 :
505 :
506 0 : if (attachmentFlags.test(AUTODATA)) {
507 0 : ostringstream oss;
508 0 : oss << "Data subset '"<<contentLocation<<"': ";
509 0 : oss << "found an unexpected attachment 'autoData' in integration #" << integrationNum_ << ".";
510 0 : throw SDMDataObjectReaderException(oss.str());
511 0 : }
512 :
513 0 : integration.shortCrossData_ = 0;
514 0 : integration.longCrossData_ = 0;
515 0 : integration.floatCrossData_ = 0;
516 0 : integration.nCrossData_ = 0;
517 0 : switch (integration.crossDataType()) {
518 0 : case INT32_TYPE:
519 0 : integration.longCrossData_ = longCrossData_;
520 0 : integration.nCrossData_ = nCrossData_;
521 0 : break;
522 :
523 0 : case INT16_TYPE:
524 0 : integration.shortCrossData_ = shortCrossData_;
525 0 : integration.nCrossData_ = nCrossData_;
526 0 : break;
527 :
528 0 : case FLOAT32_TYPE:
529 0 : integration.floatCrossData_ = floatCrossData_;
530 0 : integration.nCrossData_ = nCrossData_;
531 0 : break;
532 :
533 0 : default:
534 0 : throw SDMDataObjectReaderException("'"+CPrimitiveDataType::name(integration.crossDataType())+"' unexpected here.");
535 : }
536 0 : break;
537 :
538 0 : case AUTO_ONLY:
539 0 : if (!attachmentFlags.test(AUTODATA)) {
540 0 : ostringstream oss;
541 0 : oss << "Data subset '"<<contentLocation<<"': ";
542 0 : oss << "a binary attachment 'autoData' was expected.";
543 0 : throw SDMDataObjectReaderException(oss.str());
544 0 : }
545 0 : if (nAutoData_ != sdmDataObject_.dataStruct().autoData().size()) {
546 0 : ostringstream oss;
547 0 : oss << "Data subset '"<<contentLocation<<"': ";
548 0 : oss << "size of 'autoData' attachment (" << nAutoData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().autoData().size() << ")";
549 0 : throw SDMDataObjectReaderException(oss.str());
550 0 : }
551 :
552 :
553 0 : if (attachmentFlags.test(CROSSDATA)) {
554 0 : ostringstream oss;
555 0 : oss << "Data subset '"<<contentLocation<<"': ";
556 0 : oss << "found an unexpected attachment 'crossData'";
557 0 : throw SDMDataObjectReaderException(oss.str());
558 0 : }
559 :
560 0 : integration.autoData_ = autoData_;
561 0 : integration.nAutoData_ = nAutoData_;
562 :
563 0 : break;
564 :
565 0 : case CROSS_AND_AUTO:
566 0 : if (!attachmentFlags.test(AUTODATA)) {
567 0 : ostringstream oss;
568 0 : oss << "Data subset '"<<contentLocation<<"': ";
569 0 : oss << "a binary attachment 'autoData' was expected.";
570 0 : throw SDMDataObjectReaderException(oss.str());
571 0 : }
572 0 : if (nAutoData_ != sdmDataObject_.dataStruct().autoData().size()) {
573 0 : ostringstream oss;
574 0 : oss << "Data subset '"<<contentLocation<<"': ";
575 0 : oss << "size of 'autoData' attachment (" << nAutoData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().autoData().size() << ")";
576 0 : throw SDMDataObjectReaderException(oss.str());
577 0 : }
578 :
579 0 : if (!attachmentFlags.test(CROSSDATA)) {
580 0 : ostringstream oss;
581 0 : oss << "Data subset '"<<contentLocation<<"': ";
582 0 : oss << "a binary attachment 'crossData' was expected.";
583 0 : throw SDMDataObjectReaderException(oss.str());
584 0 : }
585 :
586 : // crossDataTypeSize is not currently used, skip this block
587 : // switch (integration.crossDataType()) {
588 : // case INT32_TYPE:
589 : // crossDataTypeSize = sizeof(INTCROSSDATATYPE);
590 : // break;
591 : // case INT16_TYPE:
592 : // crossDataTypeSize = sizeof(SHORTCROSSDATATYPE);
593 : // break;
594 : // case FLOAT32_TYPE:
595 : // crossDataTypeSize = sizeof(FLOATCROSSDATATYPE);
596 : // break;
597 : // default:
598 : // throw SDMDataObjectReaderException("'"+CPrimitiveDataType::name(integration.crossDataType())+"' unexpected here.");
599 : // }
600 :
601 0 : if (nCrossData_ != sdmDataObject_.dataStruct().crossData().size()) {
602 0 : ostringstream oss;
603 0 : oss << "Data subset '"<<contentLocation<<"': ";
604 0 : oss << "size of 'crossData' attachment (" << nCrossData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().crossData().size() << ")";
605 0 : throw SDMDataObjectReaderException(oss.str());
606 0 : }
607 :
608 :
609 0 : integration.shortCrossData_ = 0;
610 0 : integration.longCrossData_ = 0;
611 0 : integration.floatCrossData_ = 0;
612 0 : integration.nCrossData_ = 0;
613 0 : switch (integration.crossDataType()) {
614 0 : case INT32_TYPE:
615 0 : integration.longCrossData_ = longCrossData_;
616 0 : integration.nCrossData_ = nCrossData_;
617 0 : break;
618 :
619 0 : case INT16_TYPE:
620 0 : integration.shortCrossData_ = shortCrossData_;
621 0 : integration.nCrossData_ = nCrossData_;
622 0 : break;
623 :
624 0 : case FLOAT32_TYPE:
625 0 : integration.floatCrossData_ = floatCrossData_;
626 0 : integration.nCrossData_ = nCrossData_;
627 0 : break;
628 :
629 0 : default:
630 0 : throw SDMDataObjectReaderException("Data subset '"+contentLocation+"': '"+CPrimitiveDataType::name(integration.crossDataType())+"' unexpected here.");
631 : }
632 :
633 0 : integration.autoData_ = autoData_;
634 0 : integration.nAutoData_ = nAutoData_;
635 :
636 :
637 0 : break;
638 0 : default:
639 0 : throw SDMDataObjectReaderException("Data subset '"+contentLocation+"': unrecognized correlation mode");
640 : break;
641 : }
642 :
643 :
644 0 : if (attachmentFlags.test(ZEROLAGS)) {
645 : // Refuse the zeroLags attachment if it's not a Correlator or if the correlator is a CORRELATOR_FX (ACA).
646 0 : if ((sdmDataObject_.processorType_ != CORRELATOR) || (sdmDataObject_.correlatorType() == FX))
647 0 : throw SDMDataObjectReaderException("zeroLags are not expected from a correlator CORRELATOR_FX");
648 :
649 0 : if (nZeroLags_ != sdmDataObject_.dataStruct().zeroLags().size()) {
650 0 : ostringstream oss;
651 0 : oss << "Data subset '"<<contentLocation<<"': ";
652 0 : oss << "size of 'zeroLags' attachment (" << nZeroLags_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().zeroLags().size() << ")";
653 0 : throw SDMDataObjectReaderException(oss.str());
654 0 : }
655 0 : integration.zeroLags_ = zeroLags_;
656 0 : integration.nZeroLags_ = nZeroLags_;
657 : }
658 :
659 0 : sdmDataObject_.append(integration);
660 : }
661 :
662 0 : if (!compare("--\n--"+MIMEBOUNDARY_1))
663 0 : throw SDMDataObjectReaderException("Data subset '"+contentLocation+"': expecting a '--"+MIMEBOUNDARY_1+"' at the end of a data subset");
664 :
665 0 : find("--\n--"+MIMEBOUNDARY_1);
666 : // cout << "Exiting processMIMEIntegration" << endl;
667 0 : }
668 :
669 0 : void SDMDataObjectReader::processMIMEIntegrations() {
670 : // cout << "Entering processMIMEIntegrations" << endl;
671 :
672 0 : while (!compare("--")) {
673 : // We are one character beyond the last character of --<MIMEBOUNDARY_1>
674 : // Let's ignore the MIME Header right after the --<MIMEBOUNDARY_1>
675 : // and move to the next --<MIMEBOUNDARY_2>
676 0 : if (find("--"+MIMEBOUNDARY_2) == string::npos)
677 0 : throw SDMDataObjectReaderException("Expecting a boundary '--"+MIMEBOUNDARY_2+"' at this position");
678 :
679 : //Process the next integration.
680 0 : integrationNum_++;
681 0 : processMIMEIntegration() ;
682 : }
683 :
684 : // cout << "Exiting processMIMEIntegrations" << endl;
685 0 : }
686 :
687 0 : void SDMDataObjectReader::processMIMESubscan() {
688 : // cout << "Entering processMIMESubscan" << endl;
689 :
690 : // We are one character beyond the last character of --<MIMEBOUNDARY_1>
691 : // Let's ignore the MIME Header right after the --<MIMEBOUNDARY_1>
692 : // and move to the next --<MIMEBOUNDARY_2>
693 : // We are 1 character beyond the end of --<MIMEBOUNDARY_2>
694 0 : if (find("--"+MIMEBOUNDARY_2) == string::npos)
695 0 : throw SDMDataObjectReaderException("Expecting a boundary '--"+MIMEBOUNDARY_2+"' at this position");
696 :
697 :
698 0 : string contentLocation = getContentLocation();
699 : // cout << contentLocation << endl;
700 : #ifndef WITHOUT_BOOST
701 : boost::regex r(" *"+sdmDataObject_.projectPath() + "desc.xml");
702 :
703 : // Extract the Subset name and the suffix number (which must be equal to 1).
704 : boost::cmatch what;
705 : if (!boost::regex_match(contentLocation.c_str(), what, r)) {
706 : ostringstream oss;
707 : oss << "Invalid Content-Location field '" << contentLocation <<"' in MIME header of the subset";
708 : throw SDMDataObjectReaderException(oss.str());
709 : }
710 : #else
711 0 : std::regex r(" *"+sdmDataObject_.projectPath() + "desc.xml");
712 :
713 : // Extract the Subset name and the suffix number (which must be equal to 1).
714 0 : std::cmatch what;
715 0 : if (!std::regex_match(contentLocation.c_str(), what, r)) {
716 0 : ostringstream oss;
717 0 : oss << "Invalid Content-Location field '" << contentLocation <<"' in MIME header of the subset";
718 0 : throw SDMDataObjectReaderException(oss.str());
719 0 : }
720 : #endif
721 :
722 0 : SDMDataSubset subscan(&sdmDataObject_);
723 :
724 : // The SDMDataSubset header.
725 0 : processMIMESDMDataSubsetHeader(subscan);
726 :
727 :
728 : // Process the binary attachments.
729 0 : attachmentFlags.reset();
730 0 : integrationNum_++;
731 0 : while(!EOD() && !compare("--")) {
732 0 : processBinaryAttachment(MIMEBOUNDARY_2, subscan);
733 : }
734 :
735 0 : if (EOD()) throw SDMDataObjectReaderException("Unexpected end of data");
736 :
737 : // Now check if the binary attachments found are compatible with the correlation mode.
738 : // and if their sizes are equal to what is announced in the global header.
739 :
740 : // Start with the only mandatory attachment : autoData.
741 0 : if (!attachmentFlags.test(AUTODATA)) {
742 0 : ostringstream oss;
743 0 : oss << "Binary attachment 'autoData' was expected in integration #" << integrationNum_;
744 0 : throw SDMDataObjectReaderException(oss.str());
745 0 : }
746 0 : if (nAutoData_ != sdmDataObject_.dataStruct().autoData().size()) {
747 0 : ostringstream oss;
748 0 : oss << "Size of 'autoData' attachment (" << nAutoData_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().autoData().size() << ")";
749 0 : throw SDMDataObjectReaderException(oss.str());
750 0 : }
751 :
752 0 : subscan.autoData_ = autoData_;
753 0 : subscan.nAutoData_ = nAutoData_;
754 :
755 :
756 : // And now consider the optional attachments.
757 :
758 : // The actualDurations are optional. They may be absent.
759 0 : if (!attachmentFlags.test(ACTUALDURATIONS)) {
760 : // No actualDurations binary attachment found, ok then set everything to 0.
761 0 : subscan.actualDurations_ = 0;
762 0 : subscan.nActualDurations_ = 0;
763 : }
764 : else {
765 : // actualDurations found
766 : // Check size conformity
767 0 : if (nActualDurations_ != sdmDataObject_.dataStruct().actualDurations().size()) {
768 0 : ostringstream oss;
769 0 : oss << "Size of 'actualDurations' attachment (" << nActualDurations_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().actualDurations().size() << ")";
770 0 : throw SDMDataObjectReaderException(oss.str());
771 0 : }
772 :
773 : // Set pointer and size
774 0 : subscan.actualDurations_ = actualDurations_;
775 0 : subscan.nActualDurations_ = nActualDurations_;
776 : }
777 :
778 :
779 : // The actualTimes are optional. They may be absent.
780 0 : if (!attachmentFlags.test(ACTUALTIMES)) {
781 : // No actualTimes binary attachment found, ok then set everything to 0.
782 0 : subscan.actualTimes_ = 0;
783 0 : subscan.nActualTimes_ = 0;
784 : }
785 : else {
786 : // actualTimes found
787 : // Check size conformity
788 0 : if (nActualTimes_ != sdmDataObject_.dataStruct().actualTimes().size()) {
789 0 : ostringstream oss;
790 0 : oss << "Size of 'actualTimes' attachment (" << nActualTimes_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().actualTimes().size() << ")";
791 0 : throw SDMDataObjectReaderException(oss.str());
792 0 : }
793 :
794 : // Set pointer and size
795 0 : subscan.actualTimes_ = actualTimes_;
796 0 : subscan.nActualTimes_ = nActualTimes_;
797 : }
798 :
799 :
800 : // The flags are optional. They may be absent.
801 0 : if (!attachmentFlags.test(FLAGS)) {
802 : // No flags binary attachment found, ok then set everything to 0.
803 0 : subscan.flags_ = 0;
804 0 : subscan.nFlags_ = 0;
805 : }
806 : else {
807 : // flags found
808 : // Check size conformity
809 0 : if (nFlags_ != sdmDataObject_.dataStruct().flags().size()) {
810 0 : ostringstream oss;
811 0 : oss << "Size of 'flags' attachment (" << nFlags_ << ") is not equal to the size announced in the header (" << sdmDataObject_.dataStruct().flags().size() << ")";
812 0 : throw SDMDataObjectReaderException(oss.str());
813 0 : }
814 :
815 : // Set pointer and size
816 0 : subscan.flags_ = flags_;
817 0 : subscan.nFlags_ = nFlags_;
818 : }
819 :
820 : // And finally let's check that no unexpected binary attachment was found.
821 0 : if (attachmentFlags.test(CROSSDATA)) {
822 0 : ostringstream oss;
823 0 : oss << "Found an unexpected attachment 'crossData' in the binary attachments.";
824 0 : throw SDMDataObjectReaderException(oss.str());
825 0 : }
826 :
827 :
828 0 : if (attachmentFlags.test(ZEROLAGS)) {
829 0 : ostringstream oss;
830 0 : oss << "Found an unexpected attachment 'zeroLags' in the binary attachments.";
831 0 : throw SDMDataObjectReaderException(oss.str());
832 0 : }
833 :
834 0 : sdmDataObject_.tpDataSubset(subscan);
835 :
836 :
837 0 : if (!compare("--\n--"+MIMEBOUNDARY_1))
838 0 : throw SDMDataObjectReaderException("Expecting a '--"+MIMEBOUNDARY_1+"' at the end of a data subset");
839 :
840 0 : find("--\n--"+MIMEBOUNDARY_1);
841 0 : }
842 :
843 0 : void SDMDataObjectReader::processMIME() {
844 : // cout << "Entering processMIME" << endl;
845 : // Let's find the opening boundary
846 0 : if (find("--"+MIMEBOUNDARY_1) == string::npos)
847 0 : throw SDMDataObjectReaderException("Expecting a first boundary '--"+MIMEBOUNDARY_1+"'.");
848 :
849 : // Check the Content-Location of the MIME header ...but do nothing special with it...
850 0 : string contentLocation=getContentLocation();
851 :
852 : // Detect SDMDataHeader.
853 0 : processMIMESDMDataHeader();
854 :
855 : // Do we have packed data (i.e. only one SDMDataSubset grouping all the integrations) or one integration per SDMDataSubset (i.e. per timestamp) ?
856 0 : if (sdmDataObject_.hasPackedData()) {
857 0 : processMIMESubscan();
858 : }
859 : else {
860 0 : processMIMEIntegrations();
861 : }
862 :
863 :
864 : // if (sdmDataObject_.isCorrelation()) {
865 : // // Process integrations.
866 : // processMIMEIntegrations();
867 : // }
868 : // else if (sdmDataObject_.isTP()){
869 : // // cout << "TP data" << endl;
870 : // if (sdmDataObject_.dimensionality() == 0) {
871 : // processMIMESubscan();
872 : // }
873 : // else {
874 : // processMIMEIntegrations();
875 : // }
876 : // }
877 : // else {
878 : // // cout << "Unrecognized type of binary data." << endl;
879 : // }
880 : //cout << "Exiting processMIME" << endl;
881 0 : }
882 :
883 0 : const SDMDataObject & SDMDataObjectReader::read(const char * buffer, unsigned long int size, bool fromFile) {
884 0 : if (!fromFile) read_ = MEMORY_;
885 :
886 : // Set up all sensitive pointers and sizes.
887 0 : data_ = (char *)buffer;
888 0 : dataSize_ = size;
889 0 : position_ = 0;
890 0 : endPosition_ = size;
891 :
892 : // And process the MIME message
893 0 : sdmDataObject_.valid_ = true;
894 0 : processMIME();
895 :
896 0 : sdmDataObject_.owns();
897 0 : return sdmDataObject_;
898 : }
899 :
900 0 : const SDMDataObject& SDMDataObjectReader::ref() const {
901 0 : if (read_ == UNKNOWN_)
902 0 : throw SDMDataObjectReaderException("a reference to an SDMDataObject cannot be obtained as long as the method 'read' has not been called.");
903 0 : return sdmDataObject_;
904 : }
905 :
906 0 : const SDMDataObject* SDMDataObjectReader::ptr() const {
907 0 : if (read_ == UNKNOWN_)
908 0 : throw SDMDataObjectReaderException("a reference to an SDMDataObject cannot be obtained as long as the method 'read' has not been called.");
909 0 : return &sdmDataObject_;
910 : }
911 :
912 0 : void SDMDataObjectReader::done() {
913 0 : switch (read_) {
914 0 : case UNKNOWN_:
915 : case MEMORY_:
916 0 : break;
917 0 : case FILE_:
918 0 : munmap((caddr_t) data_, dataSize_);
919 0 : close(filedes_);
920 0 : break;
921 : }
922 0 : sdmDataObject_.done();
923 0 : read_ = UNKNOWN_;
924 0 : }
925 :
926 0 : const SDMDataObject& SDMDataObjectReader::sdmDataObject() {
927 0 : return sdmDataObject_;
928 : }
929 :
930 :
931 0 : const SDMDataObject & SDMDataObjectReader::read(string filename) {
932 :
933 : struct stat fattr; // stat64 fattr;
934 :
935 : unsigned long int filesize;
936 0 : char* data = 0;
937 : // Open the file.
938 0 : errno = 0;
939 : #ifdef __APPLE__
940 : if ( (filedes_ = open(filename.c_str(), O_RDONLY )) == -1) {
941 : #else
942 0 : if ( (filedes_ = open(filename.c_str(), O_RDONLY | O_LARGEFILE)) == -1) {
943 : #endif
944 0 : string message(strerror(errno));
945 0 : throw SDMDataObjectReaderException("Could not open file '" + filename + "'. The message was '" + message + "'");
946 0 : }
947 0 : read_ = FILE_;
948 :
949 : // Get its size.
950 0 : errno = 0;
951 0 : int status = fstat(filedes_,&fattr); // fstat64(filedes_,&fattr);
952 0 : if (status == -1) {
953 0 : string message(strerror(errno));
954 0 : throw SDMDataObjectReaderException("Could not retrieve size of file '" + filename + "'. The message was '" + message + "'");
955 0 : }
956 0 : filesize = fattr.st_size;
957 :
958 : // Map it to virtual memory address space.
959 0 : errno = 0;
960 :
961 0 : data = (char *) mmap((caddr_t)0, filesize, PROT_READ, MAP_SHARED, filedes_, (off_t)0);
962 0 : if ( ((unsigned long) data) == 0xffffffff) {
963 0 : string message(strerror(errno));
964 0 : throw SDMDataObjectReaderException("Could not map file '" + filename + "' to memory. The message was '" + message + "'");
965 0 : }
966 :
967 : // cout << "Successfully mapped file." << endl;
968 : // And delegate to the other read (memory buffer) method.
969 0 : return read(data, filesize, true);
970 : }
971 :
972 : // SDMDataObjectReader::
973 :
974 : } // namespace asdmbinaries
975 :
|