79 qmlRegisterUncreatableType<ZblLogReader>(
"org.zuble.qml", 1, 0,
80 "ZblLogReader",
"ZblLogReader is an internal Zuble type. Use ZLogReader instead.");
84 qmlRegisterUncreatableType<ZLogViewport>(
"org.zuble.qml", 1, 0,
85 "ZLogViewport",
"Use ZLogReader to create ZLogViewport objects.");
96 QByteArray metaRecord;
98 zDebug() <<
"Loading log file metadata.";
104 if(metaRecord.size() == 0)
106 zWarning() <<
"Log file id and metadata not available.";
110 int uuidEndPos = metaRecord.indexOf(
'}');
114 zWarning() <<
"Log file id not available.";
118 QUuid uuid(metaRecord.left(uuidEndPos+1));
122 zWarning() <<
"Log file id invalid format.";
127 zDebug() <<
"Log file id: " << uuid.toByteArray();
132 if(metaRecord.size() <= uuidEndPos+1)
134 zWarning() <<
"Log file metadata not available.";
140 QByteArray metaBytes = metaRecord.right(metaRecord.size() - uuidEndPos - 1);
142 zDebug() <<
"Log file metadata: " << metaBytes;
144 QJsonDocument doc = QJsonDocument::fromJson(metaBytes, &er);
146 if(er.error != QJsonParseError::NoError)
148 zWarning() <<
"Log file metadata parse error: " 154 zDebug() <<
"Log file metadata parsed OK.";
158 zWarning() <<
"Log file metadata format error. Metadata must be a JSON object.";
162 QJsonObject jsonObj = doc.object();
184 QMutexLocker lock(&
m_lock);
250 bool loadMarkupColumn,
251 QVariantMap contextMap)
256 qint64 rowsFound = 0;
257 qint64 rowsStored = 0;
264 errMsg =
"You must pass a ZLogViewport object as first argument.";
266 emit
loadComplete(viewport, searchParams, eof, errMsg, contextMap);
281 errMsg =
"Log file doesn't contain requested rows.";
283 emit
loadComplete(viewport, searchParams, eof, errMsg, contextMap);
317 bool loadMarkupColumn,
327 qint64 parsedLines = 0;
329 qint64 currentIndex = 0;
330 const qint64 finalIndex = rowCount - 1;
342 if(loadMarkupColumn && searchParams->
origin() != -1)
345 ZblLogScanner scanner(searchParams, flags, loadMarkupColumn);
349 zDebug() <<
"Skipping log file metadata.";
366 if(!eof && (currentIndex < finalIndex))
368 errMsg =
"Log file doesn't contain requested rows.";
371 if(!cellBuffer.isEmpty())
374 storedCount += parsedLines;
391 errMsg =
"JSON parse error at seek position: %1, %2";
393 errMsg = errMsg.arg(seekPos);
394 errMsg = errMsg.arg(logError.
parseError.errorString());
400 errMsg =
"Log file format error at seek position: %1, " 401 "Each Zuble log record must be a JSON array.";
409 errMsg =
"Log file format error at seek position: %1, " 410 "Each Zuble log record must be a JSON array.";
424 if((rowCount != -1) && (currentIndex == finalIndex))
427 storedCount += parsedLines;
435 storedCount += parsedLines;
448 const QByteArray& ba,
461 QJsonDocument doc = QJsonDocument::fromJson(ba, &logError.
parseError);
463 if(logError.
parseError.error != QJsonParseError::NoError)
473 "Each Zuble log record must be a JSON array " 474 "containing %1 cells per row.";
479 QJsonArray ja = doc.array();
481 const int arraySize = ja.size();
487 "Can't load log record: Record size mismatch! Expecting %1 " 488 "cells per row but file has %2.";
493 QVariantList va(ja.toVariantList());
497 qint64 recordID = va.at(0).toLongLong();
501 va.append(QVariant(seekPos));
502 va.append(QVariant(ba.size()));
507 va.append(QVariant(
""));
509 cellBuffer.append(va);
518 cellBuffer.append(va);
542 const qint64 recordCount = logRecords.size();
544 zDebug() <<
"Record count = " << recordCount;
545 zDebug() <<
"Rows needed = " << rowCount;
547 if(recordCount == 0 || rowCount == 0)
549 zDebug() <<
"rows stored = " << 0;
558 qint64 index = recordCount - rowCount;
563 zDebug() <<
"index = " << index;
567 rowsStored = recordCount - index;
571 for(lostRecords = 0; index < recordCount; index++)
575 qint64 seekPos = seekPositions.at(index);
579 logRecords.at(index),
590 QString errMsg =
"JSON parse error at seek position: %1, %2";
592 errMsg.arg(seekPos).arg(logError.
parseError.errorString());
600 QString errMsg =
"Log file format error at seek position: %1, %2";
609 rowsStored -= lostRecords;
611 zDebug() <<
"rows stored = " << rowsStored;
615 zDebug() <<
"Saving log records to data model, cell count: " << cellBuffer.size();
628 bool loadMarkupColumn,
642 qint64 chunkSize = 1024;
645 bool moreData =
true;
651 qint64 rowsNeeded = rowCount;
655 if(loadMarkupColumn && searchParams->
origin() != -1)
658 ZblLogScanner scanner(searchParams, flags, loadMarkupColumn);
671 qint64 startSeek = seekPos;
673 seekPos = seekPos - chunkSize;
675 zDebug() <<
"Seeking back - startSeek = " << startSeek
676 <<
", chunkSize = " << chunkSize;
680 zDebug() <<
"Seek at or past beginning of file: " << seekPos;
691 while(seekPos < startSeek)
693 zDebug() <<
"Reading next line at seekPos:" << seekPos;
697 if(!ba.isEmpty() && !discard)
699 zDebug() <<
"Saving line at seekPos: " << seekPos;
701 rowBuffer.push_back(ba);
702 seekBuffer.push_back(seekPos);
706 zDebug() <<
"Discarding line at seekPos: " << seekPos;
713 const int rowsFound = rowBuffer.size();
715 zDebug() <<
"Rows found = " << rowsFound;
716 zDebug() <<
"Rows needed = " << rowsNeeded;
719 rowBuffer, seekBuffer, rowsNeeded, viewport, scanner);
723 foundCount += rowsFound;
724 storedCount += rowsStored;
726 if(rowsStored >= rowsNeeded)
731 rowsNeeded -= rowsFound;
733 zDebug() <<
"Rows left to fetch: " << rowsNeeded;
739 seekPos = seekBuffer.at(0);
740 zDebug() <<
"Setting new seekPos: " << seekPos;
744 zDebug() <<
"Not setting new seekPos: " << seekPos;
761 bool loadMarkupColumn
768 qint64 rowsFound = 0;
769 qint64 rowsStored = 0;
774 errMsg =
"You must pass a ZLogViewport object as first argument.";
775 emit zViewport->
moveComplete(rowsFound, rowsStored, eod, errMsg);
813 emit zViewport->
moveComplete(rowsFound, rowsStored, eod, errMsg);
824 zWarning() <<
"Programming error: searchmark parameter must be " 825 "a ZLogSearch object.";
838 for(
int i=0; i < logLinks.
m_links.count(); i++)
846 qint64 seekPos = nextNode.
m_value.toLongLong();
851 zDebug() <<
"Skipping log file metadata.";
868 QJsonDocument doc = QJsonDocument::fromJson(ba, &logError.
parseError);
870 if(logError.
parseError.error != QJsonParseError::NoError)
873 zWarning() <<
"JSON parse error reading log file at seekposition " 874 << seekPos <<
": " << logError.
parseError.errorString();
877 else if(!doc.isArray())
881 "Each Zuble log record must be a JSON array " 882 "containing %1 cells per row.";
885 zWarning() <<
"JSON format error reading log file at seekposition " 890 QJsonArray ja = doc.array();
892 const int arraySize = ja.size();
898 "Can't load log record: Record size mismatch! Expecting %1 " 899 "cells per row but file has %2.";
906 zDebug() <<
"link message text = " << messageValue.toString();
908 results.addMessageText(nextNode.
m_index, messageValue.toString());
912 QVariant vResults(QVariant::fromValue<ZblLogLinkList>(results));
914 zDebug() <<
"Sending linkMessageText signal...";
917 QMetaObject::invokeMethod(search,
"onLinkTextComplete", Qt::QueuedConnection, Q_ARG(QVariant, vResults));
void initializeMetadata()
Reads the log file metadata contained in the first record of the log file.
QList< LinkNode > m_links
Q_INVOKABLE void prependCells(QVariant data, bool truncateModel=false)
Asynchronously converts an array of cell data into one or more rows of model data and prepends it to ...
QJsonParseError parseError
void timerEvent(QTimerEvent *event)
Periodically sends notifyFileSize signal.
static QThread * m_readerThread
A single background thread services all ZblLogReader objects.
Q_INVOKABLE void appendCells(QVariant data, bool truncateModel=false)
Asynchronously converts an array of cell data into one or more rows of model data and appends it to t...
static QMutex m_lock
Histogram buffer caches bytes of file data for subsequent parsing into log records.
This class performs log file I/O operations and JSON parsing in a background thread on behalf of a ZL...
Q_INVOKABLE void clearData()
Removes all data from the model. Roles and role names remain intact.
void move(QObject *viewport, qint64 recordCount, qint64 seekIndex, bool forward, ZblLogSearchParams searchParams, bool loadMarkupColumn)
Moves the viewport forward or backward a specific number of records.
This class allows Zuble log file viewer text search operations to pass parameters between threads...
#define ZBL_REGISTER_LOGGED_OBJECT
bool outputHighlightedText()
Determine if scanner is enabled.
QList< qint64 > zSeekBuffer
QString loadRowsBehind(ZLogViewport *viewport, qint64 seekPos, qint64 rowCount, const ZblLogSearchParams *searchParams, bool loadMarkupColumn, qint64 &foundCount, qint64 &storedCount, bool &bof)
Prepends log data records to the data model scanning backward in the file from the specified seek pos...
QString loadRowsAhead(ZLogViewport *viewport, qint64 seekPos, qint64 rowCount, bool truncate, const ZblLogSearchParams *searchParams, bool loadMarkupColumn, qint64 &foundCount, qint64 &storedCount, bool &eof)
Appends log records to the data model scanning foreward in the file from the specified seek position...
bool outputMarkupColumn()
Determine if scanner will output markup column when scanning log record data models.
ZTableModel * getZModel()
Returns the data model containing the viewport's log records.
bool m_fileActive
true if input file is open and ready for reading, false otherwise.
void openFile(const QString &filePath, QVariantMap contextMap=QVariantMap())
Opens the log file in a concurrent background thread. Sends the openComplete signal when open is comp...
QVariantMap m_metadata
A QVariantMap containing meta information about the log file.
A log viewport encapsulates a ZTableModel containing a contiguous subset of log records from a Zuble ...
static void zInit(int logRecordRoleCount)
Must be called only once before calling newLogReader();.
void storeViewportData(ZDataRow &cellData, ZLogViewport *viewport, bool truncate=false)
Appends data to the back of the viewport's data model.
void parseNextFileRecord(ZLogViewport *viewport, const QByteArray &ba, qint64 seekPos, ZblLogScanner &logScanner, ZDataRow &cellBuffer, ZblLogError &logError)
Picks the next file record off the input stream buffer, parses it and contatenates results to the dat...
void loadViewport(QObject *viewport, qint64 seekPosition, qint64 viewportSize, ZblLogSearchParams searchParams, bool loadMarkupColumn=false, QVariantMap contextMap=QVariantMap())
Loads a viewport's log record data model with the a set of records located by a file seek index...
static ZblLogReader * newLogReader()
creates a new ZblLogReader object and moves it to the shared background log reader thread...
#define ZBL_DEFINE_LOGGED_OBJECT(class_name)
This class allows Zuble log file viewer text search operations to pass log record link parameters bet...
This two dimensional table model is used to store and manipulate data.
void loadRecordLinkMessageText(QObject *searchmark, QVariant links)
Loads the message text from the log file for the specified ZLogSearch object.
int m_timerID
Timer ID for file size timer. Zero == timer inactive.
static int m_readerCount
Counts instances of ZblLogReader objects.
void loadComplete(bool endOfData, QString errorMsg, QVariantMap context)
Signals that loading of the viewport requested by a call to loadRecordByIndex() has completed...
static qint64 m_defaultPageSize
number of rows in a default page.
void moveComplete(qint64 rowsFound, qint64 rowsStored, bool endOfData, QString errorMsg)
Signals that moving of the viewport requested by a call to move() has completed.
void openComplete(bool success, QString errorMsg, QVariantMap contextMap)
Sent when the file open operation started by calling openFile() has completed.
static int m_recordRoleCount
Number of roles in a log record.
Log record scanner/highlighter object encapsulates logic for locating and marking up search text...
QQueue< QByteArray > zRowBuffer
static QString resolvePath(const QString &path, bool includeUrlScheme=true)
Converts relative file paths into canonical file paths. Paths prefixed with prefix are mapped relativ...
static const int m_updateBatchSize
The number of rows to accumulate before sending a row update to the data model. Batching rows reduces...
A class for passing log file input error information.
void loadComplete(QObject *viewport, ZblLogSearchParams searchParams, bool endOfData, QString errorMsg, QVariantMap context)
Sent when loading log records into a viewport by calling ZblLogReader::loadViewport() has completed...
QString formatErrorString
qint64 m_optimalCount
Identifies the first record in the viewport.
Q_INVOKABLE void sync()
Blocks thread until model's event queue has been processed.
ZblLogReader(QObject *parent=0)
static const qint64 m_maxLineSize
The maximum number of bytes a log record can contain.
QVariantList markupOrdinalRoleList(QVariantList data)
Returns a highlighted text string for the specified QVariant objects.
ZBL_DECLARE_LOGGED_OBJECT QFile m_inputFile
Input file object from which log records will be read.
QUuid m_uuid
A UUID that uniquely identifies this log file.
int parseAndStoreViewportData(zRowBuffer &logRecords, zSeekBuffer &seekPositions, qint64 rowCount, ZLogViewport *viewport, ZblLogScanner &logScanner)
Parses rows from a row buffer and prepends them to the front of the viewport's data model...
This object encapsulates search operation parameters, results, and steady state.
QList< QVariant > ZDataRow
Represents a single row (or column for column headers) of data cell values for a single role...
qint64 m_firstRecordPos
File position of the first log record of the search operation.
void notifyFileSize(qint64 fileSize)
Periodically signals the current log file size.