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