* Iterative interface to decompress the next log statement (if there are any) * in the log file and optionally prints it via outputFd. The log statements * are output in the order in which they appear in the log which may not be * in chronological order. * * \param[out] logMsg * Log message that's decompressed; the contents are valid until * the next invocation to this fun
| 1963 | * False indicates there are no more logs or there's an error |
| 1964 | */ |
| 1965 | bool |
| 1966 | Log::Decoder::getNextLogStatement(LogMessage &logMsg, |
| 1967 | FILE *outputFd) { |
| 1968 | if (bufferFragment->hasNext()) { |
| 1969 | bufferFragment->decompressNextLogStatement(outputFd, |
| 1970 | logMsgsPrinted, |
| 1971 | logMsg, |
| 1972 | checkpoint, |
| 1973 | fmtId2metadata, |
| 1974 | -1, |
| 1975 | nullptr); |
| 1976 | return true; |
| 1977 | } |
| 1978 | |
| 1979 | logMsg.reset(); |
| 1980 | |
| 1981 | // Decoder was never 'opened' properly |
| 1982 | if (filename.empty() || !inputFd) |
| 1983 | return false; |
| 1984 | |
| 1985 | // We've read the end of the file or an error |
| 1986 | if (feof(inputFd) || !good) |
| 1987 | return false; |
| 1988 | |
| 1989 | while(!bufferFragment->hasNext() && !feof(inputFd) && good) { |
| 1990 | EntryType entry = peekEntryType(inputFd); |
| 1991 | bool wrapAround; |
| 1992 | |
| 1993 | switch (entry) { |
| 1994 | case EntryType::BUFFER_EXTENT: |
| 1995 | if (bufferFragment->readBufferExtent(inputFd, &wrapAround)) { |
| 1996 | ++numBufferFragmentsRead; |
| 1997 | break; |
| 1998 | } |
| 1999 | |
| 2000 | fprintf(stderr, "Internal Error: Corrupted BufferExtent\r\n"); |
| 2001 | good = false; |
| 2002 | return false; |
| 2003 | |
| 2004 | case EntryType::CHECKPOINT: |
| 2005 | if (readDictionary(inputFd, true)) { |
| 2006 | |
| 2007 | if (outputFd) |
| 2008 | fprintf(outputFd, "\r\n# New execution started\r\n"); |
| 2009 | |
| 2010 | break; |
| 2011 | } |
| 2012 | |
| 2013 | good = false; |
| 2014 | return false; |
| 2015 | |
| 2016 | case EntryType::LOG_MSGS_OR_DIC: |
| 2017 | good = readDictionaryFragment(inputFd); |
| 2018 | break; |
| 2019 | |
| 2020 | case EntryType::INVALID: |
| 2021 | // Consume padding |
| 2022 | while (!feof(inputFd) && peekEntryType(inputFd) == INVALID) |