code format
This commit is contained in:
@@ -5,22 +5,22 @@
|
||||
* \~russian Бинарный лог
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Class for write binary data to logfile, and read or playback this data
|
||||
Andrey Bychkov work.a.b@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Class for write binary data to logfile, and read or playback this data
|
||||
Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIBINARYLOG_H
|
||||
@@ -32,32 +32,32 @@
|
||||
//! \~\brief
|
||||
//! \~english Binary log
|
||||
//! \~russian Бинарный лог
|
||||
class PIP_EXPORT PIBinaryLog: public PIIODevice
|
||||
{
|
||||
class PIP_EXPORT PIBinaryLog: public PIIODevice {
|
||||
PIIODEVICE(PIBinaryLog, "binlog");
|
||||
|
||||
public:
|
||||
explicit PIBinaryLog();
|
||||
virtual ~PIBinaryLog();
|
||||
|
||||
//! \brief Play modes for \a PIBinaryLog
|
||||
enum PlayMode {
|
||||
PlayRealTime /*! Play in system realtime, default mode */ ,
|
||||
PlayVariableSpeed /*! Play in software realtime with speed, set by \a setSpeed */ ,
|
||||
PlayStaticDelay /*! Play with custom static delay, ignoring timestamp */
|
||||
PlayRealTime /*! Play in system realtime, default mode */,
|
||||
PlayVariableSpeed /*! Play in software realtime with speed, set by \a setSpeed */,
|
||||
PlayStaticDelay /*! Play with custom static delay, ignoring timestamp */
|
||||
};
|
||||
|
||||
|
||||
//! \brief Different split modes for writing \a PIBinaryLog, which can separate files by size, by time or by records count
|
||||
enum SplitMode {
|
||||
SplitNone /*! Without separate, default mode */ ,
|
||||
SplitTime /*! Separate files by record time */ ,
|
||||
SplitSize /*! Separate files by size */ ,
|
||||
SplitCount /*! Separate files by records count */
|
||||
SplitNone /*! Without separate, default mode */,
|
||||
SplitTime /*! Separate files by record time */,
|
||||
SplitSize /*! Separate files by size */,
|
||||
SplitCount /*! Separate files by records count */
|
||||
};
|
||||
|
||||
//! \brief Struct contains information about all records with same ID
|
||||
struct PIP_EXPORT BinLogRecordInfo {
|
||||
BinLogRecordInfo() {
|
||||
id = count = 0;
|
||||
id = count = 0;
|
||||
minimum_size = maximum_size = 0;
|
||||
}
|
||||
int id;
|
||||
@@ -89,81 +89,96 @@ public:
|
||||
|
||||
|
||||
//! Current \a PlayMode
|
||||
PlayMode playMode() const {return play_mode;}
|
||||
PlayMode playMode() const { return play_mode; }
|
||||
|
||||
//! Current \a SplitMode
|
||||
SplitMode splitMode() const {return split_mode;}
|
||||
SplitMode splitMode() const { return split_mode; }
|
||||
|
||||
//! Current directory where billogs wiil be saved
|
||||
PIString logDir() const {return property("logDir").toString();}
|
||||
|
||||
PIString logDir() const { return property("logDir").toString(); }
|
||||
|
||||
//! Returns current file prefix
|
||||
PIString filePrefix() const {return property("filePrefix").toString();}
|
||||
|
||||
PIString filePrefix() const { return property("filePrefix").toString(); }
|
||||
|
||||
//! Default ID, used in \a write function
|
||||
int defaultID() const {return default_id;}
|
||||
|
||||
int defaultID() const { return default_id; }
|
||||
|
||||
//! Returns current play speed
|
||||
double playSpeed() const {return play_speed > 0 ? 1. / play_speed : 0.;}
|
||||
double playSpeed() const { return play_speed > 0 ? 1. / play_speed : 0.; }
|
||||
|
||||
//! Returns current play delay
|
||||
PISystemTime playDelay() const {return play_delay;}
|
||||
PISystemTime playDelay() const { return play_delay; }
|
||||
|
||||
//! Returns current binlog file split time
|
||||
PISystemTime splitTime() const {return split_time;}
|
||||
PISystemTime splitTime() const { return split_time; }
|
||||
|
||||
//! Returns current binlog file split size
|
||||
llong splitFileSize() const {return split_size;}
|
||||
llong splitFileSize() const { return split_size; }
|
||||
|
||||
//! Returns current binlog file split records count
|
||||
int splitRecordCount() const {return split_count;}
|
||||
int splitRecordCount() const { return split_count; }
|
||||
|
||||
//! Returns if rapid start enabled
|
||||
bool rapidStart() const {return rapid_start;}
|
||||
|
||||
bool rapidStart() const { return rapid_start; }
|
||||
|
||||
//! Create binlog file with Filename = path
|
||||
void createNewFile(const PIString &path);
|
||||
|
||||
void createNewFile(const PIString & path);
|
||||
|
||||
//! Set \a PlayMode
|
||||
void setPlayMode(PlayMode mode) {setProperty("playMode", (int)mode);}
|
||||
void setPlayMode(PlayMode mode) { setProperty("playMode", (int)mode); }
|
||||
|
||||
//! Set \a SplitMode
|
||||
void setSplitMode(SplitMode mode) {setProperty("splitMode", (int)mode);}
|
||||
void setSplitMode(SplitMode mode) { setProperty("splitMode", (int)mode); }
|
||||
|
||||
//! Set path to directory where binlogs will be saved
|
||||
void setLogDir(const PIString & path) {setProperty("logDir", path);}
|
||||
|
||||
void setLogDir(const PIString & path) { setProperty("logDir", path); }
|
||||
|
||||
//! Set file prefix, used to
|
||||
void setFilePrefix(const PIString & prefix) {setProperty("filePrefix", prefix);}
|
||||
|
||||
void setFilePrefix(const PIString & prefix) { setProperty("filePrefix", prefix); }
|
||||
|
||||
//! Set defaultID, used in \a write function
|
||||
void setDefaultID(int id) {setProperty("defaultID", id);}
|
||||
|
||||
void setDefaultID(int id) { setProperty("defaultID", id); }
|
||||
|
||||
//! If enabled BinLog \a ThreadedRead starts without delay for first record, i.e. first record will be readed immediately
|
||||
void setRapidStart(bool enabled) {setProperty("rapidStart", enabled);}
|
||||
void setRapidStart(bool enabled) { setProperty("rapidStart", enabled); }
|
||||
|
||||
//! Set play speed to "speed", default value is 1.0x
|
||||
//! Also this function set \a playMode to \a PlayVariableSpeed
|
||||
void setPlaySpeed(double speed) {setPlayMode(PlayVariableSpeed); setProperty("playSpeed", speed);}
|
||||
void setPlaySpeed(double speed) {
|
||||
setPlayMode(PlayVariableSpeed);
|
||||
setProperty("playSpeed", speed);
|
||||
}
|
||||
|
||||
//! Setting static delay between records, default value is 1 sec
|
||||
//! Also this function set \a playMode to \a PlayStaticDelay
|
||||
void setPlayDelay(const PISystemTime & delay) {setPlayMode(PlayStaticDelay); setProperty("playDelay", delay);}
|
||||
void setPlayDelay(const PISystemTime & delay) {
|
||||
setPlayMode(PlayStaticDelay);
|
||||
setProperty("playDelay", delay);
|
||||
}
|
||||
|
||||
//! Set \a playMode to \a PlayRealTime
|
||||
void setPlayRealTime() {setPlayMode(PlayRealTime);}
|
||||
void setPlayRealTime() { setPlayMode(PlayRealTime); }
|
||||
|
||||
//! Set binlog file split time
|
||||
//! Also this function set \a splitMode to \a SplitTime
|
||||
void setSplitTime(const PISystemTime & time) {setSplitMode(SplitTime); setProperty("splitTime", time);}
|
||||
void setSplitTime(const PISystemTime & time) {
|
||||
setSplitMode(SplitTime);
|
||||
setProperty("splitTime", time);
|
||||
}
|
||||
|
||||
//! Set binlog file split size
|
||||
//! Also this function set \a splitMode to \a SplitSize
|
||||
void setSplitFileSize(llong size) {setSplitMode(SplitSize); setProperty("splitFileSize", size);}
|
||||
void setSplitFileSize(llong size) {
|
||||
setSplitMode(SplitSize);
|
||||
setProperty("splitFileSize", size);
|
||||
}
|
||||
|
||||
//! Set binlog file split records count
|
||||
//! Also this function set \a splitMode to \a SplitCount
|
||||
void setSplitRecordCount(int count) {setSplitMode(SplitCount); setProperty("splitRecordCount", count);}
|
||||
void setSplitRecordCount(int count) {
|
||||
setSplitMode(SplitCount);
|
||||
setProperty("splitRecordCount", count);
|
||||
}
|
||||
|
||||
//! Set pause while playing via \a threadedRead or writing via write
|
||||
void setPause(bool pause);
|
||||
@@ -171,82 +186,90 @@ public:
|
||||
//! Set function wich returns new binlog file path when using split mode.
|
||||
//! Overrides internal file path generator (logdir() + prefix() + current_time()).
|
||||
//! To restore internal file path generator set this function to "nullptr".
|
||||
void setFuncGetNewFilePath(std::function<PIString()> f) {f_new_path = f;}
|
||||
void setFuncGetNewFilePath(std::function<PIString()> f) { f_new_path = f; }
|
||||
|
||||
//! Write one record to BinLog file, with ID = id, id must be greather than 0
|
||||
int writeBinLog(int id, PIByteArray data) {return writeBinLog(id, data.data(), data.size_s());}
|
||||
|
||||
int writeBinLog(int id, PIByteArray data) { return writeBinLog(id, data.data(), data.size_s()); }
|
||||
|
||||
//! Write one record to BinLog file, with ID = id, id must be greather than 0
|
||||
int writeBinLog(int id, const void * data, int size);
|
||||
|
||||
//! Write one RAW record to BinLog file, with ID = id, Timestamp = time
|
||||
int writeBinLog_raw(int id, const PISystemTime &time, const PIByteArray &data) {return writeBinLog_raw(id, time, data.data(), data.size_s());}
|
||||
int writeBinLog_raw(int id, const PISystemTime &time, const void * data, int size);
|
||||
int writeBinLog_raw(int id, const PISystemTime & time, const PIByteArray & data) {
|
||||
return writeBinLog_raw(id, time, data.data(), data.size_s());
|
||||
}
|
||||
int writeBinLog_raw(int id, const PISystemTime & time, const void * data, int size);
|
||||
|
||||
//! Returns count of writed records
|
||||
int writeCount() const {return write_count;}
|
||||
|
||||
int writeCount() const { return write_count; }
|
||||
|
||||
//! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed
|
||||
PIByteArray readBinLog(int id = 0, PISystemTime * time = 0, int * readed_id = 0);
|
||||
|
||||
|
||||
//! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed
|
||||
int readBinLog(int id, void * read_to, int max_size, PISystemTime * time = 0, int * readed_id = 0);
|
||||
|
||||
|
||||
//! Returns binary log file size
|
||||
llong logSize() const {return log_size;}
|
||||
llong logSize() const { return log_size; }
|
||||
|
||||
//! Return position in current binlog file
|
||||
llong logPos() const {return file.pos();}
|
||||
llong logPos() const { return file.pos(); }
|
||||
|
||||
//! Return true, if position at the end of BinLog file
|
||||
bool isEnd() const {if (isClosed()) return true; return file.isEnd();}
|
||||
|
||||
bool isEnd() const {
|
||||
if (isClosed()) return true;
|
||||
return file.isEnd();
|
||||
}
|
||||
|
||||
//! Returns if BinLog file is empty
|
||||
bool isEmpty() const;
|
||||
|
||||
//! Returns BinLog pause status
|
||||
bool isPause() const {return is_pause;}
|
||||
|
||||
bool isPause() const { return is_pause; }
|
||||
|
||||
//! Returns id of last readed record
|
||||
int lastReadedID() const {return lastrecord.id;}
|
||||
int lastReadedID() const { return lastrecord.id; }
|
||||
|
||||
//! Returns timestamp of last readed record
|
||||
PISystemTime lastReadedTimestamp() const {return lastrecord.timestamp;}
|
||||
PISystemTime lastReadedTimestamp() const { return lastrecord.timestamp; }
|
||||
|
||||
//! Returns timestamp of log start
|
||||
PISystemTime logStartTimestamp() const {return startlogtime;}
|
||||
PISystemTime logStartTimestamp() const { return startlogtime; }
|
||||
|
||||
//!Set custom file header, you can get it back when read this binlog
|
||||
//! Set custom file header, you can get it back when read this binlog
|
||||
void setHeader(const PIByteArray & header);
|
||||
|
||||
//!Get custom file header
|
||||
//! Get custom file header
|
||||
PIByteArray getHeader();
|
||||
|
||||
#ifdef DOXYGEN
|
||||
//! Read one message from binlog file, with ID contains in "filterID" or any ID, if "filterID" is empty
|
||||
int read(void *read_to, int max_size);
|
||||
|
||||
int read(void * read_to, int max_size);
|
||||
|
||||
//! Write one record to BinLog file, with ID = "defaultID"
|
||||
int write(const void * data, int size);
|
||||
#endif
|
||||
|
||||
//! Array of ID, that BinLog can read from binlog file, when use \a read function, or in \a ThreadedRead
|
||||
PIVector<int> filterID;
|
||||
|
||||
|
||||
//! Go to begin of BinLog file
|
||||
void restart();
|
||||
|
||||
//! Get binlog info \a BinLogInfo
|
||||
BinLogInfo logInfo() const {if (is_indexed) return binfo; return getLogInfo(path());}
|
||||
BinLogInfo logInfo() const {
|
||||
if (is_indexed) return binfo;
|
||||
return getLogInfo(path());
|
||||
}
|
||||
|
||||
//! Get binlog index \a BinLogIndex, need \a createIndex before getting index
|
||||
const PIVector<BinLogIndex> & logIndex() const {return index;}
|
||||
|
||||
const PIVector<BinLogIndex> & logIndex() const { return index; }
|
||||
|
||||
//! Create index of current binlog file
|
||||
bool createIndex();
|
||||
|
||||
//! Return if current binlog file is indexed
|
||||
bool isIndexed() {return is_indexed;}
|
||||
bool isIndexed() { return is_indexed; }
|
||||
|
||||
//! Find nearest record of time \"time\". Returns -1 if not indexed or time less than first record
|
||||
int posForTime(const PISystemTime & time);
|
||||
@@ -261,22 +284,25 @@ public:
|
||||
bool seek(llong filepos);
|
||||
|
||||
//! Get current record index (position record in file)
|
||||
int pos() const {if (is_indexed) return current_index; return -1;}
|
||||
int pos() const {
|
||||
if (is_indexed) return current_index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
|
||||
|
||||
//! \fn PIString createNewFile()
|
||||
//! \brief Create new binlog file in \a logDir, if successful returns filename, else returns empty string.
|
||||
//! Filename is like \a filePrefix + "yyyy_MM_dd__hh_mm_ss.binlog"
|
||||
|
||||
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
|
||||
//! \fn void fileEnd()
|
||||
//! \brief Raise on file end while reading
|
||||
|
||||
|
||||
//! \fn void fileError()
|
||||
//! \brief Raise on file creation error
|
||||
|
||||
@@ -284,7 +310,7 @@ public:
|
||||
//! \brief Raise on new file created
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
EVENT_HANDLER(PIString, createNewFile);
|
||||
EVENT(fileEnd);
|
||||
EVENT(fileError);
|
||||
@@ -298,20 +324,22 @@ public:
|
||||
static bool cutBinLog(const BinLogInfo & src, const PIString & dst, int from, int to);
|
||||
|
||||
//! Create new binlog from serial splitted binlogs "src"
|
||||
static bool joinBinLogsSerial(const PIStringList & src, const PIString & dst, std::function<bool (const PIString &, PISystemTime)> progress = nullptr);
|
||||
static bool joinBinLogsSerial(const PIStringList & src,
|
||||
const PIString & dst,
|
||||
std::function<bool(const PIString &, PISystemTime)> progress = nullptr);
|
||||
|
||||
protected:
|
||||
PIString constructFullPathDevice() const override;
|
||||
void configureFromFullPathDevice(const PIString & full_path) override;
|
||||
PIPropertyStorage constructVariantDevice() const override;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d) override;
|
||||
ssize_t readDevice(void *read_to, ssize_t max_size) override;
|
||||
ssize_t readDevice(void * read_to, ssize_t max_size) override;
|
||||
ssize_t writeDevice(const void * data, ssize_t size) override;
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
void propertyChanged(const char * s) override;
|
||||
bool threadedRead(const uchar *readed, ssize_t size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
|
||||
bool threadedRead(const uchar * readed, ssize_t size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
|
||||
|
||||
private:
|
||||
struct PIP_EXPORT BinLogRecord {
|
||||
@@ -324,7 +352,7 @@ private:
|
||||
bool writeFileHeader();
|
||||
bool checkFileHeader();
|
||||
BinLogRecord readRecord();
|
||||
static void parseLog(PIFile *f, BinLogInfo *info, PIVector<BinLogIndex> * index);
|
||||
static void parseLog(PIFile * f, BinLogInfo * info, PIVector<BinLogIndex> * index);
|
||||
void moveIndex(int i);
|
||||
static PIString getLogfilePath(const PIString & log_dir, const PIString & prefix);
|
||||
|
||||
@@ -347,7 +375,7 @@ private:
|
||||
};
|
||||
|
||||
//! \relatesalso PICout \brief Output operator PIBinaryLog::BinLogInfo to PICout
|
||||
inline PICout operator <<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
|
||||
inline PICout operator<<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
|
||||
s.space();
|
||||
s.saveAndSetControls(0);
|
||||
s << "[PIBinaryLog] " << bi.path << "\n";
|
||||
@@ -360,7 +388,8 @@ inline PICout operator <<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
|
||||
s << "Invalid empty file";
|
||||
s.restoreControls();
|
||||
return s;
|
||||
} if (bi.records_count < 0 && bi.records_count > -4) {
|
||||
}
|
||||
if (bi.records_count < 0 && bi.records_count > -4) {
|
||||
s << "Invalid file or corrupted signature";
|
||||
s.restoreControls();
|
||||
return s;
|
||||
@@ -373,7 +402,7 @@ inline PICout operator <<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
|
||||
s << "read records " << bi.records_count << " in " << bi.records.size() << " types, log size " << bi.log_size;
|
||||
s << "\nlog start " << bi.start_time << " , log end " << bi.end_time;
|
||||
PIVector<int> keys = bi.records.keys();
|
||||
for (int i : keys) {
|
||||
for (int i: keys) {
|
||||
PIBinaryLog::BinLogRecordInfo bri = bi.records.at(i);
|
||||
s << "\n record id " << bri.id << " , count " << bri.count;
|
||||
s << "\n record start " << bri.start_time << " , end " << bri.end_time;
|
||||
|
||||
Reference in New Issue
Block a user