MCPcopy Create free account
hub / github.com/PlatformLab/NanoLog / decompressTo

Method decompressTo

runtime/Log.cc:1794–1945  ·  view source on GitHub ↗

* Decompress the log file that was open()-ed and print the log messages out * in chronological order. * * \param outputFd * The file descriptor to print the log messages to * * \return * The number of log messages encountered. A negative value indicates error */

Source from the content-addressed store, hash-verified

1792 * The number of log messages encountered. A negative value indicates error
1793 */
1794int64_t
1795Log::Decoder::decompressTo(FILE* outputFd)
1796{
1797 if (filename.empty() || !inputFd)
1798 return -1;
1799
1800 // In ordered decompression, we must sort the entries by time which means
1801 // we need to buffer in 3 rounds of NanoLog output. We need more than one
1802 // round of output because the compression is non-quiescent, which means
1803 // that as we're outputting the nth buffer, new entries may be added to
1804 // n-1 and n, and the entries in n could logically come /before/ the new
1805 // entries added to n-1. The reason why we need at least 3 is due to an
1806 // implementation detail in StagingBuffer whereby one peek() does not
1807 // return all the data and at least 2 peek()'s are needed to deplete a
1808 // buffer.
1809 static const uint32_t stagesToBuffer = 3;
1810 std::vector<BufferFragment*> stages[stagesToBuffer];
1811
1812 // Running number of stages being kept in stages
1813 uint32_t stagesBuffered = 0;
1814
1815 // Indicates that all stages must be depleted before continuing
1816 // processing the log file. This should only be true when we detect
1817 // the start of a new execution(s) log appended to inputFd or we
1818 // reached the end of the current file
1819 bool mustDepleteAllStages = false;
1820
1821 LogMessage logArguments;
1822 while (!feof(inputFd) && good) {
1823
1824 // Step 1: Read in up to a certain number of "stages" of BufferFragments
1825 mustDepleteAllStages = false;
1826 while (!feof(inputFd) && good && !mustDepleteAllStages) {
1827 EntryType entry = peekEntryType(inputFd);
1828 bool newStage = false;
1829
1830 switch (entry) {
1831 case EntryType::BUFFER_EXTENT:
1832 {
1833 BufferFragment *bf = allocateBufferFragment();
1834 good = bf->readBufferExtent(inputFd, &newStage);
1835 ++numBufferFragmentsRead;
1836
1837 if (good)
1838 stages[stagesBuffered].push_back(bf);
1839
1840 break;
1841 }
1842 case EntryType::CHECKPOINT:
1843 // New logical start to the logs detected, at this point
1844 // we should make sure we've printed all the buffered logs
1845 // before continuing to parse the next logical start.
1846 if (!stages[0].empty()) {
1847 mustDepleteAllStages = true;
1848 break;
1849 }
1850
1851 // We're safe, all the stages are empty

Callers 2

mainFunction · 0.80
TEST_FFunction · 0.80

Calls 5

peekEntryTypeFunction · 0.85
readBufferExtentMethod · 0.80
getNextLogTimestampMethod · 0.80
hasNextMethod · 0.80

Tested by 1

TEST_FFunction · 0.64