source: pacpusframework/trunk/src/FileLib/src/DbiteFile.cpp@ 280

Last change on this file since 280 was 280, checked in by Marek Kurdej, 10 years ago

Major: DbiteException uses boost::exception.

  • Property svn:executable set to *
File size: 23.9 KB
Line 
1// %pacpus:license{
2// This file is part of the PACPUS framework distributed under the
3// CECILL-C License, Version 1.0.
4// %pacpus:license}
5/// @version $Id: DbiteFile.cpp 76 2013-01-10 17:05:10Z kurdejma $
6
7#include <Pacpus/kernel/DbiteFile.h>
8#include <Pacpus/kernel/DbiteException.h>
9#include <Pacpus/kernel/DbiteFileTypes.h>
10#include <Pacpus/kernel/Log.h>
11
12#include <boost/exception/detail/exception_ptr.hpp>
13#include <boost/exception/errinfo_api_function.hpp>
14#include <boost/exception/errinfo_file_name.hpp>
15#include <boost/exception/errinfo_nested_exception.hpp>
16#include <cassert>
17#include <cmath>
18#include <iostream>
19#include <limits>
20#include <sstream>
21
22using boost::copy_exception;
23using boost::errinfo_api_function;
24using boost::errinfo_file_name;
25using boost::errinfo_nested_exception;
26using boost::exception_ptr;
27using namespace pacpus;
28using std::fstream;
29using std::ios_base;
30using std::min;
31using std::max;
32using std::numeric_limits;
33using std::streamsize;
34using std::string;
35using std::stringstream;
36
37// FIXME: record size is only 8-bit long!
38typedef int8_t VariableDataSizeT;
39
40DECLARE_STATIC_LOGGER("pacpus.core.DbiteFile");
41
42namespace pacpus
43{
44 VariableDataSizeTag VariableDataSize;
45 ReadModeTag ReadMode;
46 WriteModeTag WriteMode;
47 DiagnoseModeTag DiagnoseMode;
48}
49
50bool doesFileExist(string const& path);
51
52DbiteFile::DbiteFile()
53 : mIsWriting(false)
54{
55 setPath("");
56
57 (void) ReadMode; // unused
58 (void) WriteMode; // unused
59 (void) VariableDataSize; // unused
60 (void) DiagnoseMode; // unused
61}
62
63DbiteFile::~DbiteFile()
64{
65 if (isOpen()) {
66 close();
67 }
68}
69
70DbiteFile::operator string()
71{
72 static const int64_t kMicrosInSecond = 1000 * 1000;
73 stringstream os;
74
75 os << "Signature : " << getSignature() << "\n";
76 os << "Version : " << getVersion() << "\n";
77 os << "Header size : " << getDataOffset() << " [bytes]" << "\n";
78 os << "Record size : " << getRecordSize() << " [bytes]" << "\n";
79 os << "Data type : " << getType() << "\n";
80 os << "Time min. : " << getTimeMin() << "\n";
81 os << "Time max. : " << getTimeMax() << "\n";
82 os << "Duration : " << (getTimeMax() - getTimeMin()) / kMicrosInSecond << " [seconds]" << "\n";
83 os << "File size : " << getFileSize() << " [bytes]" << "\n";
84 os << "Record count : " << getRecordCount() << "\n";
85
86 return os.str();
87}
88
89const string & DbiteFile::getPath() const
90{
91 return mPath;
92}
93
94void DbiteFile::setPath(const string & path)
95{
96 mPath = path;
97}
98
99void DbiteFile::open(const string & path, ReadModeTag)
100{
101 mIsWriting = false;
102 if (isOpen()) {
103 LOG_DEBUG("file is already open, closing...");
104 close();
105 }
106
107 setPath(path);
108
109 ios_base::openmode openmode = ios_base::binary | ios_base::in;
110 mFile.open(getPath().c_str(), openmode);
111 try {
112 checkFileOpen();
113 } catch (DbiteException & e) {
114 (void) e; // unused
115 LOG_ERROR("Dbite exception: " << e.what());
116 close();
117 BOOST_THROW_EXCEPTION(DbiteException("cannot open file for reading")
118 << errinfo_file_name(mPath)
119 << errinfo_ios_base_open_mode(openmode)
120 );
121 }
122
123 try {
124 readHeader();
125 } catch (DbiteException& e) {
126 (void) e; // unused
127 LOG_ERROR("Dbite exception: " << e.what());
128 // TODO: readAndDiagnoseHeader();
129 close();
130 BOOST_THROW_EXCEPTION(DbiteException("cannot read header")
131 << errinfo_nested_exception(copy_exception(e))
132 );
133 }
134 verifyHeader();
135 goToDataBegin();
136}
137
138void DbiteFile::open(const string & path, WriteModeTag)
139{
140 openWriteMode(path);
141}
142
143void DbiteFile::open(const string & path, WriteModeTag, hdfile_header_t::DataTypeT type, hdfile_header_t::DataSizeT dataSize)
144{
145 openWriteMode(path, type);
146 setRecordSize(dataSize);
147}
148
149void DbiteFile::open(const string & path, WriteModeTag, hdfile_header_t::DataTypeT type, VariableDataSizeTag tag)
150{
151 openWriteMode(path, type);
152 setRecordSize(tag);
153}
154
155void DbiteFile::openWriteMode(const string & path, hdfile_header_t::DataTypeT type)
156{
157 openWriteMode(path);
158 setType(type);
159}
160
161void DbiteFile::openWriteMode(const string & path)
162{
163 mIsWriting = true;
164 if (isOpen()) {
165 LOG_DEBUG("file is already open, closing...");
166 close();
167 }
168
169 setPath(path);
170 bool fileExists = doesFileExist(path);
171 ios_base::openmode openmode;
172 if (fileExists) {
173 openmode = ios_base::binary | ios_base::in | ios_base::out;
174 } else {
175 openmode = ios_base::binary | ios_base::out;
176 }
177 mFile.open(getPath().c_str(), openmode);
178 if (!isOpen()) {
179 LOG_ERROR("cannot open file for writing");
180 BOOST_THROW_EXCEPTION(DbiteException("cannot open file for writing")
181 << errinfo_ios_base_open_mode(openmode)
182 );
183 }
184
185 if (fileExists) {
186 // file exists
187 LOG_DEBUG("file already exists, appending");
188 try {
189 readHeader();
190 // TODO: check if same type and record size
191 } catch (DbiteException & e) {
192 (void) e; // unused
193 LOG_ERROR("Dbite exception: " << e.what());
194 // TODO: readAndDiagnoseHeader();
195 close();
196 BOOST_THROW_EXCEPTION(DbiteException("cannot read header"));
197 }
198 } else {
199 // file does not exist
200 initializeHeader();
201 writeHeader();
202 }
203 //goToDataBegin();
204 goToFileEnd();
205}
206
207void DbiteFile::initializeHeader()
208{
209 setSignature();
210 setType(FILE_DBT_UNKNOWN);
211 setVersion(VERSION_NUMBER);
212 setDataOffset(sizeof(hdfile_header_t));
213 setRecordSize(0);
214 // same as header size
215 setFileSize(getDataOffset());
216 setTimeMin(numeric_limits<road_time_t>::max());
217 setTimeMax(numeric_limits<road_time_t>::min());
218 setRecordCount(0);
219}
220
221void DbiteFile::close()
222{
223 if (!isOpen()) {
224 LOG_WARN("file is not open");
225 return;
226 }
227 closeDbite();
228 setPath("");
229}
230
231void DbiteFile::closeDbite()
232{
233 if (mIsWriting) {
234 try {
235 writeHeader();
236 } catch (DbiteException & e) {
237 (void) e; // unused
238 LOG_ERROR("cannot write header on close: " << e.what());
239 }
240 }
241 mFile.close();
242}
243
244bool DbiteFile::isOpen() const
245{
246 return mFile.is_open();
247}
248
249void DbiteFile::goToFileBegin()
250{
251 LOG_DEBUG("goToFileBegin()");
252 mFile.clear();
253 setReadPosition(0);
254 setWritePosition(0);
255}
256
257void DbiteFile::goToDataBegin()
258{
259 LOG_DEBUG("goToDataBegin()");
260 LOG_TRACE("getDataOffset() = " << getDataOffset());
261 mFile.clear();
262 setReadPosition(getDataOffset());
263 setWritePosition(getDataOffset());
264}
265
266void DbiteFile::goToFileEnd()
267{
268 LOG_TRACE("goToFileEnd()");
269 LOG_TRACE("getFileSize() = " << getFileSize());
270 mFile.clear();
271 // do not use fstream::seekg/seekp(0, ios_base::end),
272 // because in case of write failure,
273 // we should write at position=getFileSize() which can be before the actual file end
274 setReadPosition(getFileSize());
275 setWritePosition(getFileSize());
276}
277
278int64_t DbiteFile::getReadPosition()
279{
280 checkFileOpen();
281 return mFile.tellg();
282}
283
284int64_t DbiteFile::getWritePosition()
285{
286 checkFileOpen();
287 return mFile.tellp();
288}
289
290void DbiteFile::setReadPosition(int64_t offset, ios_base::seekdir direction)
291{
292 LOG_TRACE("set read position = " << offset << " direction = " << direction);
293 checkFileOpen();
294 mFile.seekg(offset, direction);
295 if (mFile.fail()) {
296 LOG_ERROR("failed to set write position");
297 }
298}
299
300void DbiteFile::setReadPosition(int64_t position)
301{
302 LOG_TRACE("set read position = " << position);
303 checkFileOpen();
304 mFile.seekg(position);
305 if (mFile.fail()) {
306 LOG_ERROR("failed to set read position");
307 }
308}
309
310void DbiteFile::setWritePosition(int64_t offset, ios_base::seekdir direction)
311{
312 LOG_TRACE("set write position = " << offset << " direction = " << direction);
313 checkFileOpen();
314 mFile.seekp(offset, direction);
315 if (mFile.fail()) {
316 LOG_ERROR("failed to set write position");
317 }
318}
319
320void DbiteFile::setWritePosition(int64_t position)
321{
322 LOG_TRACE("set write position = " << position);
323 checkFileOpen();
324 mFile.seekp(position);
325 if (mFile.fail()) {
326 LOG_ERROR("failed to set write position");
327 }
328}
329
330const hdfile_header_t & DbiteFile::getHeader() const
331{
332 return mHeader;
333}
334
335hdfile_header_t & DbiteFile::header()
336{
337 return mHeader;
338}
339
340void DbiteFile::readHeader()
341{
342 goToFileBegin();
343 checkFileOpen();
344 read((char *)(&mHeader), sizeof(mHeader));
345 LOG_DEBUG("file: " << getPath());
346 LOG_TRACE("header read:\n" << string(*this));
347}
348
349void DbiteFile::verifyHeader()
350{
351 // verify file size
352 const int64_t realFileSize = getRealFileSize();
353 const hdfile_header_t::FileSizeT fileSize = getFileSize();
354 if (realFileSize != fileSize) {
355 LOG_WARN("real file size different than header information");
356 LOG_INFO("real file size = " << realFileSize);
357 LOG_INFO("file size = " << fileSize);
358 }
359
360 if (getVersion() != VERSION_NUMBER) {
361 LOG_ERROR("bad version number");
362 BOOST_THROW_EXCEPTION(DbiteException("bad version number"));
363 }
364
365 if (!isSignatureCorrect()) {
366 LOG_ERROR("bad signature");
367 BOOST_THROW_EXCEPTION(DbiteException("bad signature"));
368 }
369
370 LOG_DEBUG("header verified");
371}
372
373void DbiteFile::writeHeader()
374{
375 LOG_DEBUG("writing header:\n" << string(*this));
376
377 goToFileBegin();
378
379 LOG_DEBUG("begin position=" << getWritePosition());
380
381 const size_t bytesToWrite = sizeof(mHeader);
382 write((char *)(&mHeader), bytesToWrite);
383 LOG_DEBUG("header written");
384
385 LOG_DEBUG("final position=" << getWritePosition());
386}
387
388string DbiteFile::getSignature() const
389{
390 const char signature[] = { getHeader().Signature[0], getHeader().Signature[1], getHeader().Signature[2], getHeader().Signature[3], '\0' };
391 return signature;
392}
393
394bool DbiteFile::isSignatureCorrect() const
395{
396 if ('R' != getHeader().Signature[0]) {
397 return false;
398 }
399 if ('O' != getHeader().Signature[1]) {
400 return false;
401 }
402 if ('A' != getHeader().Signature[2]) {
403 return false;
404 }
405 if ('D' != getHeader().Signature[3]) {
406 return false;
407 }
408 return true;
409}
410
411void DbiteFile::setSignature()
412{
413 header().Signature[0] = 'R';
414 header().Signature[1] = 'O';
415 header().Signature[2] = 'A';
416 header().Signature[3] = 'D';
417}
418
419hdfile_header_t::DataTypeT DbiteFile::getType() const
420{
421 return getHeader().Type;
422}
423
424void DbiteFile::setType(hdfile_header_t::DataTypeT type)
425{
426 header().Type = type;
427}
428
429hdfile_header_t::VersionT DbiteFile::getVersion() const
430{
431 return getHeader().VersionNumber;
432}
433
434void DbiteFile::setVersion(hdfile_header_t::VersionT version)
435{
436 header().VersionNumber = version;
437}
438
439hdfile_header_t::DataOffsetT DbiteFile::getDataOffset() const
440{
441 return getHeader().DataOffset;
442}
443
444void DbiteFile::setDataOffset(hdfile_header_t::DataOffsetT dataOffset)
445{
446 header().DataOffset = dataOffset;
447}
448
449hdfile_header_t::DataSizeT DbiteFile::getRecordSize() const
450{
451 return getHeader().DataSize;
452}
453
454void DbiteFile::setRecordSize(hdfile_header_t::DataSizeT recordSize)
455{
456 header().DataSize = recordSize;
457}
458
459void DbiteFile::setRecordSize(VariableDataSizeTag)
460{
461 header().DataSize = hdfile_header_t::kVariableRecordSize;
462}
463
464hdfile_header_t::FileSizeT DbiteFile::getFileSize() const
465{
466 if (getHeader().FileSize < getHeader().DataOffset) {
467 LOG_WARN("wrong header information: file size lesser than data offset");
468 }
469 return getHeader().FileSize;
470}
471
472void DbiteFile::setFileSize(hdfile_header_t::FileSizeT fileSize)
473{
474 header().FileSize = fileSize;
475}
476
477int64_t DbiteFile::getRealFileSize()
478{
479 checkFileOpen();
480
481 mFile.clear();
482 // save position
483 int64_t oldReadPosition = getReadPosition();
484 int64_t oldWritePosition = getWritePosition();
485
486 // go to file end and get position = file size
487 goToFileEnd();
488 int64_t fileSize = mFile.tellg();
489
490 // restore position
491 setReadPosition(oldReadPosition);
492 setWritePosition(oldWritePosition);
493 return fileSize;
494}
495
496road_time_t DbiteFile::getTimeMin() const
497{
498 return getHeader().TimeMin;
499}
500
501void DbiteFile::setTimeMin(road_time_t time)
502{
503 header().TimeMin = time;
504}
505
506road_time_t DbiteFile::getTimeMax() const
507{
508 return getHeader().TimeMax;
509}
510
511void DbiteFile::setTimeMax(road_time_t time)
512{
513 header().TimeMax = time;
514}
515
516hdfile_header_t::RecordCountT DbiteFile::getRecordCount() const
517{
518 return getHeader().NbRecords;
519}
520
521void DbiteFile::setRecordCount(hdfile_header_t::RecordCountT recourdCount)
522{
523 header().NbRecords = recourdCount;
524}
525
526bool DbiteFile::isVariableDataSize() const
527{
528 return hdfile_header_t::kVariableRecordSize == getRecordSize();
529}
530
531bool DbiteFile::readRecord(size_t recordIndex, road_time_t & time, road_timerange_t & timeRange, char * data, size_t & dataSize)
532{
533 LOG_DEBUG("reading record no. " << recordIndex);
534
535 if (isVariableDataSize()) {
536 LOG_ERROR("cannot read nth record in a variable");
537 BOOST_THROW_EXCEPTION(DbiteException("cannot read nth record in a variable"));
538 }
539
540 int64_t nthRecordPosition = getDataOffset() + recordIndex * (getRecordSize() + sizeof(road_time_t) + sizeof(road_timerange_t));
541 LOG_DEBUG(recordIndex << "th record position = " << nthRecordPosition);
542 if (getFileSize() < nthRecordPosition) {
543 LOG_WARN("wanted to read past the file end");
544 //BOOST_THROW_EXCEPTION(DbiteException("wanted to read past the file end"));
545 }
546 mFile.clear();
547 setReadPosition(nthRecordPosition);
548
549 return readRecord(time, timeRange, data, dataSize);
550}
551
552bool DbiteFile::readRecord(road_time_t & time, road_timerange_t & timeRange, char * buffer, size_t & bufferSize, const ReadDirection & direction)
553{
554 if (!buffer) {
555 LOG_WARN("data buffer must be a non-NULL pointer");
556 BOOST_THROW_EXCEPTION(DbiteException("data buffer must be a non-NULL pointer"));
557 }
558
559 return readRecordNoBufferCheck(time, timeRange, buffer, bufferSize, direction);
560}
561
562bool DbiteFile::readRecord(road_time_t & time, road_timerange_t & timeRange, char * buffer, const ReadDirection & direction)
563{
564 size_t bufferSize = getRecordSize();
565 return readRecord(time, timeRange, buffer, bufferSize, direction);
566}
567
568bool DbiteFile::readRecord(road_time_t & time, road_timerange_t & timeRange, const ReadDirection & direction)
569{
570 size_t bufferSize = 0;
571 return readRecordNoBufferCheck(time, timeRange, (char *) NULL, bufferSize, direction);
572}
573
574bool DbiteFile::readRecordNoBufferCheck(road_time_t & time, road_timerange_t & timeRange, char * buffer, size_t & bufferSize, const ReadDirection & direction)
575{
576 switch (direction) {
577 case ReadForward:
578 return readRecordForward(time, timeRange, buffer, bufferSize);
579 break;
580
581 case ReadBackward:
582 return readRecordBackward(time, timeRange, buffer, bufferSize);
583 break;
584
585 default:
586 assert(false && "wrong ReadDirection parameter");
587 return false;
588 }
589}
590
591bool DbiteFile::readRecordForward(road_time_t & time, road_timerange_t & timeRange, char * buffer, size_t & bufferSize)
592{
593 LOG_TRACE("reading record...");
594 checkFileOpen();
595
596 int64_t initialPosition = getReadPosition();
597 LOG_TRACE("initial position = " << initialPosition);
598
599 ////////////////////////////////////////
600 // read acquisition time
601 mFile.read((char *)(&time), sizeof(time));
602 if (!mFile) {
603 if (isEndOfFile()) {
604 bufferSize = 0;
605 return false;
606 }
607 LOG_ERROR("cannot read acquisition time");
608 BOOST_THROW_EXCEPTION(DbiteException("cannot read acquisition time")
609 << errinfo_file_name(mPath)
610 << errinfo_api_function("read")
611 );
612 }
613
614 ////////////////////////////////////////
615 // read acquisition time range
616 read((char *)(&timeRange), sizeof(timeRange));
617
618 ////////////////////////////////////////
619 // get data and record size
620 size_t dataSize = 0;
621 size_t recordSize = sizeof(time) + sizeof(timeRange);
622 if (isVariableDataSize()) {
623 recordSize += 2 * sizeof(VariableDataSizeT);
624
625 // read record size
626 VariableDataSizeT readVarDataSize = 0;
627 read((char *)(&readVarDataSize), sizeof(VariableDataSizeT));
628 dataSize = static_cast<size_t>(readVarDataSize);
629 LOG_DEBUG("variable record size = " << dataSize);
630 } else {
631 dataSize = getRecordSize();
632 }
633 recordSize += dataSize;
634
635 ////////////////////////////////////////
636 // read/skip data
637 if (buffer) {
638 if (bufferSize < dataSize) {
639 LOG_WARN("buffer is smaller than the record size");
640 LOG_INFO("buffer size = " << bufferSize);
641 LOG_INFO("data size = " << dataSize);
642 BOOST_THROW_EXCEPTION(DbiteException("buffer is smaller than the data size"));
643 // TODO: don't throw exception, but read only as much data as possible
644 }
645
646 // read data
647 read(buffer, dataSize);
648
649 if (isVariableDataSize()) {
650 // read record size
651 VariableDataSizeT readVarDataSize = 0;
652 read((char *)(&readVarDataSize), sizeof(VariableDataSizeT));
653 size_t varDataSize = static_cast<size_t>(readVarDataSize);
654 LOG_TRACE("variable record size = " << varDataSize);
655
656 if (dataSize != varDataSize) {
657 LOG_WARN("corrupted data: data sizes differ");
658 LOG_INFO("data size (before) = " << dataSize);
659 LOG_INFO("data size (after) = " << varDataSize);
660 }
661 }
662 } else {
663 // skip data
664 setReadPosition(dataSize, ios_base::cur);
665 if (isVariableDataSize()) {
666 setReadPosition(dataSize, ios_base::cur);
667 }
668 }
669
670 ////////////////////////////////////////
671 // check how many bytes were read/skipped
672 int64_t positionDifference = getReadPosition() - initialPosition;
673 if (positionDifference != recordSize) {
674 LOG_WARN("should be read : " << recordSize << " [bytes]");
675 LOG_WARN("was actually read: " << positionDifference << " [bytes]");
676 }
677 return true;
678}
679
680bool DbiteFile::readRecordBackward(road_time_t & time, road_timerange_t & timeRange, char * buffer, size_t & bufferSize)
681{
682 int64_t initialPosition = getReadPosition();
683 LOG_TRACE("initial position = " << initialPosition);
684
685 size_t dataSize = 0;
686 size_t recordSize = sizeof(time) + sizeof(timeRange);
687 if (isVariableDataSize()) {
688 recordSize += 2 * sizeof(VariableDataSizeT);
689
690 // go back sizeof(VariableDataSizeT)
691 setReadPosition(initialPosition - sizeof(VariableDataSizeT));
692
693 // read VariableDataSizeT
694 VariableDataSizeT readVarDataSize = 0;
695 read((char *)(&readVarDataSize), sizeof(VariableDataSizeT));
696 dataSize = static_cast<size_t>(readVarDataSize);
697 LOG_DEBUG("variable record size = " << dataSize);
698 } else {
699 dataSize = getRecordSize();
700 }
701 // recordSize = sizeof(time) + sizeof(timeRange) + dataSize + [2 * sizeof(VariableDataSizeT)]
702 recordSize += dataSize;
703
704 // go back to the beginning of the previous record
705 setReadPosition(initialPosition - recordSize);
706
707 bool readResult = false;
708 try {
709 // read forward
710 readResult = readRecordForward(time, timeRange, buffer, bufferSize);
711 } catch (DbiteException& /*e*/) {
712 setReadPosition(initialPosition);
713 throw;
714 }
715
716 // go back to the beginning of the previous record
717 setReadPosition(initialPosition - recordSize);
718 return readResult;
719}
720
721bool DbiteFile::writeRecord(const road_time_t & time, const road_timerange_t & timeRange, const char * data, const size_t dataSize)
722{
723 LOG_DEBUG("writing record:" << "\t"
724 << "time=" << time << "\t"
725 << "time range=" << timeRange << "\t"
726 << "data size=" << dataSize);
727 checkFileOpen();
728
729 if (isVariableDataSize()) {
730 if (dataSize > static_cast<size_t>(numeric_limits<VariableDataSizeT>::max())) {
731 LOG_ERROR("variable data size too big");
732 BOOST_THROW_EXCEPTION(DbiteException("variable data size too big")
733 << errinfo_file_name(mPath)
734 );
735 }
736 }
737
738 int64_t initialPosition = getWritePosition();
739 LOG_TRACE("getFileSize() = " << getFileSize());
740 LOG_TRACE("getWritePosition() = " << getWritePosition());
741 assert(initialPosition == getFileSize());
742
743 size_t writtenBytes = 0;
744 try {
745 // write acquisition time, acquisition time range, data
746 // if variable size, then write record size before and after data
747
748 write((const char *)(&time), sizeof(time));
749 writtenBytes += sizeof(time);
750
751 write((const char *)(&timeRange), sizeof(timeRange));
752 writtenBytes += sizeof(timeRange);
753
754 if (isVariableDataSize()) {
755 write((const char *)(&dataSize), sizeof(VariableDataSizeT));
756 writtenBytes += sizeof(VariableDataSizeT);
757 }
758 write((const char *)(data), dataSize);
759 writtenBytes += dataSize;
760
761 if (isVariableDataSize()) {
762 write((const char *)(&dataSize), sizeof(VariableDataSizeT));
763 writtenBytes += sizeof(VariableDataSizeT);
764 }
765 } catch (DbiteException& e) {
766 LOG_ERROR("Dbite exception: " << e.what());
767 LOG_INFO("restoring initial write position");
768
769 // on error, go back to record start
770 setWritePosition(- (int64_t) writtenBytes, ios_base::cur);
771 throw;
772 }
773
774 // check how many bytes were written
775 int64_t finalPosition = getWritePosition();
776 int64_t positionDifference = finalPosition - initialPosition;
777 LOG_TRACE("position difference = " << positionDifference);
778 size_t totalRecordSize = dataSize + sizeof(time) + sizeof(timeRange);
779
780 setFileSize(finalPosition); // FIXME: possible loss of data, conversion int64_t -> FileSizeT
781 setRecordCount(getRecordCount() + 1);
782 setTimeMin(min(getTimeMin(), time));
783 setTimeMax(max(getTimeMax(), time));
784
785 if (positionDifference != totalRecordSize) {
786 LOG_WARN("should be written : " << totalRecordSize << " [bytes]");
787 LOG_WARN("was actually written: " << positionDifference << " [bytes]");
788 }
789 return true;
790}
791
792void DbiteFile::read(fstream::char_type * s, streamsize n)
793{
794 mFile.read(s, n);
795 if (!mFile) {
796 LOG_ERROR("cannot read data");
797 BOOST_THROW_EXCEPTION(DbiteException("cannot read data")
798 << errinfo_file_name(mPath)
799 << errinfo_api_function("read")
800 );
801 }
802}
803
804void DbiteFile::write(const fstream::char_type * s, streamsize n)
805{
806 mFile.write(s, n);
807 if (!mFile) {
808 LOG_ERROR("cannot write data");
809 BOOST_THROW_EXCEPTION(DbiteException("cannot write data")
810 << errinfo_file_name(mPath)
811 << errinfo_api_function("write")
812 );
813 }
814}
815
816bool DbiteFile::isEndOfFile()
817{
818 return mFile.eof();
819}
820
821void DbiteFile::checkFileOpen()
822{
823 if (!isOpen()) {
824 string errorMessage = "file is not open";
825 LOG_WARN(errorMessage);
826 BOOST_THROW_EXCEPTION(DbiteException(errorMessage.c_str())
827 << errinfo_file_name(mPath)
828 );
829 }
830}
831
832bool doesFileExist(const string & path)
833{
834 bool fileExist = false;
835 fstream f(path.c_str(), ios_base::in);
836 if (f.good()) {
837 fileExist = true;
838 }
839 f.close();
840 return fileExist;
841}
Note: See TracBrowser for help on using the repository browser.