libzypp  17.36.3
HistoryLogReader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
13 #include <iostream>
14 
15 #include <utility>
16 #include <zypp-core/base/InputStream>
17 #include <zypp/base/IOStream.h>
18 #include <zypp/base/Logger.h>
19 #include <zypp-core/parser/ParseException>
20 
22 
23 using std::endl;
24 
26 namespace zypp
27 {
29  namespace parser
30  {
31 
33  //
34  // class HistoryLogReader::Impl
35  //
38  {
39  Impl( Pathname &&historyFile_r, Options &&options_r, ProcessData &&callback_r )
40  : _filename( std::move(historyFile_r) )
41  , _options( std::move(options_r) )
42  , _callback( std::move(callback_r) )
43  {}
44 
45  bool parseLine( const std::string & line_r, unsigned int lineNr_r );
46 
47  void readAll( const ProgressData::ReceiverFnc & progress_r );
48  void readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r );
49  void readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r );
50 
51  void addActionFilter( const HistoryActionID & action_r )
52  {
53  if ( action_r == HistoryActionID::NONE )
54  _actionfilter.clear();
55  else
56  _actionfilter.insert( action_r.asString() );
57  }
58 
60  Options _options;
62  std::set<std::string> _actionfilter;
63  };
64 
65  bool HistoryLogReader::Impl::parseLine( const std::string & line_r, unsigned lineNr_r )
66  {
67  // parse into fields
69  str::splitEscaped( line_r, std::back_inserter(fields), "|", true );
70 
71  if ( fields.size() < 2 ) {
72  WAR << "Ignore invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl;
73  return true; // At least an action field[1] is needed!
74  }
75  fields[1] = str::trim( std::move(fields[1]) ); // for whatever reason writer is padding the action field
76 
77  if ( !_actionfilter.empty() && !_actionfilter.count( fields[1] ) )
78  return true;
79 
80  // move into data class
82  try
83  {
84  data = HistoryLogData::create( fields );
85  }
86  catch ( const Exception & excpt )
87  {
88  ZYPP_CAUGHT( excpt );
89  if ( _options.testFlag( IGNORE_INVALID_ITEMS ) )
90  {
91  WAR << "Ignore invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl;
92  return true;
93  }
94  else
95  {
96  ERR << "Invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl;
97  ParseException newexcpt( str::Str() << "Error in history log on line #" << lineNr_r );
98  newexcpt.remember( excpt );
99  ZYPP_THROW( newexcpt );
100  }
101  }
102 
103  // consume data
104  if ( _callback && !_callback( data ) )
105  {
106  WAR << "Stop parsing requested by consumer callback on line #" << lineNr_r << endl;
107  return false;
108  }
109  return true;
110  }
111 
113  {
114  InputStream is( _filename );
115  iostr::EachLine line( is );
116 
117  ProgressData pd;
118  pd.sendTo( progress_r );
119  pd.toMin();
120 
121  for ( ; line; line.next(), pd.tick() )
122  {
123  // ignore comments
124  if ( (*line)[0] == '#' )
125  continue;
126 
127  if ( ! parseLine( *line, line.lineNo() ) )
128  break; // requested by consumer callback
129  }
130 
131  pd.toMax();
132  }
133 
134  void HistoryLogReader::Impl::readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r )
135  {
136  InputStream is( _filename );
137  iostr::EachLine line( is );
138 
139  ProgressData pd;
140  pd.sendTo( progress_r );
141  pd.toMin();
142 
143  bool pastDate = false;
144  for ( ; line; line.next(), pd.tick() )
145  {
146  const std::string & s = *line;
147 
148  // ignore comments
149  if ( s[0] == '#' )
150  continue;
151 
152  if ( pastDate )
153  {
154  if ( ! parseLine( s, line.lineNo() ) )
155  break; // requested by consumer callback
156  }
157  else
158  {
159  Date logDate( s.substr( 0, s.find('|') ), HISTORY_LOG_DATE_FORMAT );
160  if ( logDate > date_r )
161  {
162  pastDate = true;
163  if ( ! parseLine( s, line.lineNo() ) )
164  break; // requested by consumer callback
165  }
166  }
167  }
168 
169  pd.toMax();
170  }
171 
172  void HistoryLogReader::Impl::readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r )
173  {
174  InputStream is( _filename );
175  iostr::EachLine line( is );
176 
177  ProgressData pd;
178  pd.sendTo( progress_r );
179  pd.toMin();
180 
181  bool pastFromDate = false;
182  for ( ; line; line.next(), pd.tick() )
183  {
184  const std::string & s = *line;
185 
186  // ignore comments
187  if ( s[0] == '#' )
188  continue;
189 
190  Date logDate( s.substr( 0, s.find('|') ), HISTORY_LOG_DATE_FORMAT );
191 
192  // past toDate - stop reading
193  if ( logDate >= toDate_r )
194  break;
195 
196  // past fromDate - start reading
197  if ( !pastFromDate && logDate > fromDate_r )
198  pastFromDate = true;
199 
200  if ( pastFromDate )
201  {
202  if ( ! parseLine( s, line.lineNo() ) )
203  break; // requested by consumer callback
204  }
205  }
206 
207  pd.toMax();
208  }
209 
211  //
212  // class HistoryLogReader
213  //
215 
216  HistoryLogReader::HistoryLogReader( Pathname historyFile_r, Options options_r, ProcessData callback_r )
217  : _pimpl( new HistoryLogReader::Impl( std::move(historyFile_r), std::move(options_r), std::move(callback_r) ) )
218  {}
219 
221  {}
222 
223  void HistoryLogReader::setIgnoreInvalidItems( bool ignoreInvalid_r )
224  { _pimpl->_options.setFlag( IGNORE_INVALID_ITEMS, ignoreInvalid_r ); }
225 
227  { return _pimpl->_options.testFlag( IGNORE_INVALID_ITEMS ); }
228 
230  { _pimpl->readAll( progress_r ); }
231 
232  void HistoryLogReader::readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r )
233  { _pimpl->readFrom( date_r, progress_r ); }
234 
235  void HistoryLogReader::readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r )
236  { _pimpl->readFromTo( fromDate_r, toDate_r, progress_r ); }
237 
239  { _pimpl->addActionFilter( action_r ); }
240 
241  } // namespace parser
243 } // namespace zypp
void readFrom(const Date &date_r, const ProgressData::ReceiverFnc &progress_r)
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \, bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
Definition: String.h:595
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
Definition: progressdata.h:229
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:424
bool next()
Advance to next line.
Definition: IOStream.cc:72
std::set< std::string > _actionfilter
Zypp history file parserReads a zypp history log file and calls the ProcessData callback passed in th...
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: progressdata.h:140
void readAll(const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Read the whole log file.
unsigned lineNo() const
Return the current line number.
Definition: IOStream.h:127
void setIgnoreInvalidItems(bool ignoreInvalid=false)
Set the reader to ignore invalid log entries and continue with the rest.
bool toMax()
Set counter value to current max value (unless no range).
Definition: progressdata.h:276
Definition: Arch.h:363
Helper to create and pass std::istream.
Definition: inputstream.h:56
Simple lineparser: Traverse each line in a file.
Definition: IOStream.h:112
RW_pointer< Impl, rw_pointer::Scoped< Impl > > _pimpl
#define ERR
Definition: Logger.h:102
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:141
bool toMin()
Set counter value to current min value.
Definition: progressdata.h:272
Store and operate on date (time_t).
Definition: Date.h:32
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:211
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:224
ignore invalid items and continue parsing
#define WAR
Definition: Logger.h:101
shared_ptr< HistoryLogData > Ptr
Maintain [min,max] and counter (value) for progress counting.
Definition: progressdata.h:131
function< bool(const HistoryLogData::Ptr &)> ProcessData
Callback type to consume a single history line split into fields.
void readAll(const ProgressData::ReceiverFnc &progress_r)
static Ptr create(FieldVector &fields_r)
Factory method creating HistoryLogData classes.
void addActionFilter(const HistoryActionID &action_r)
const std::string & asString(bool pad=false) const
std::vector< std::string > FieldVector
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:440
void readFrom(const Date &date, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Read log from specified date.
Base class for Exception.
Definition: Exception.h:146
bool tick()
Leave counter value unchanged (still alive).
Definition: progressdata.h:280
Enumeration of known history actions.
Impl(Pathname &&historyFile_r, Options &&options_r, ProcessData &&callback_r)
#define HISTORY_LOG_DATE_FORMAT
void readFromTo(const Date &fromDate, const Date &toDate, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Read log between fromDate and toDate.
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
bool ignoreInvalidItems() const
Whether the reader is set to ignore invalid log entries.
bool parseLine(const std::string &line_r, unsigned int lineNr_r)
HistoryLogReader(Pathname historyFile_r, zypp::parser::HistoryLogReader::Options options_r, ProcessData callback_r)
Ctor taking file to parse and data consumer callback.
void readFromTo(const Date &fromDate_r, const Date &toDate_r, const ProgressData::ReceiverFnc &progress_r)
void addActionFilter(const HistoryActionID &action_r)
Process only specific HistoryActionIDs.