libzypp  14.47.0
Locks.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
10 #include <set>
11 #include <fstream>
12 #include <boost/function.hpp>
13 #include <boost/function_output_iterator.hpp>
14 #include <algorithm>
15 
16 #include "zypp/base/Regex.h"
17 #include "zypp/base/String.h"
18 #include "zypp/base/Logger.h"
19 #include "zypp/base/IOStream.h"
20 #include "zypp/PoolItem.h"
21 #include "zypp/PoolQueryUtil.tcc"
22 #include "zypp/ZYppCallbacks.h"
23 #include "zypp/sat/SolvAttr.h"
24 #include "zypp/sat/Solvable.h"
25 #include "zypp/PathInfo.h"
26 
27 #undef ZYPP_BASE_LOGGER_LOGGROUP
28 #define ZYPP_BASE_LOGGER_LOGGROUP "locks"
29 
30 #include "zypp/Locks.h"
31 
32 using namespace std;
33 using namespace zypp;
34 using namespace zypp::str;
35 
36 namespace zypp
37 {
38 
39 Locks& Locks::instance()
40 {
41  static Locks _instance;
42  return _instance;
43 }
44 
46 {
47 public:
51  bool locksDirty;
52 
54 
55  Impl():locksDirty(false){}
56 };
57 
58 Locks::Locks() : _pimpl(new Impl){}
59 
61 { return _pimpl->locks.begin(); }
62 
64 { return _pimpl->locks.end(); }
65 
67 { return _pimpl->locks.size(); }
68 
69 bool Locks::empty() const
70 { return _pimpl->locks.empty(); }
71 
72 struct ApplyLock
73 {
74  void operator()(const PoolQuery& query) const
75  {
76  for_( it,query.begin(),query.end() )
77  {
78  PoolItem item(*it);
79  item.status().setLock(true,ResStatus::USER);
80  DBG << "lock "<< item.resolvable()->name();
81  }
82  }
83 };
84 
89 template <class OutputIterator>
91 {
92  LockingOutputIterator(OutputIterator& out_)
93  : out(out_)
94  {}
95 
96  void operator()(const PoolQuery& query) const
97  {
98  ApplyLock a;a(query);
99  *out++ = query;
100  }
101 
102  private:
103  OutputIterator& out;
104 };
105 
106 void Locks::readAndApply( const Pathname& file )
107 {
108  MIL << "read and apply locks from "<<file << endl;
109  PathInfo pinfo(file);
110  if ( pinfo.isExist() )
111  {
112  insert_iterator<LockList> ii( _pimpl->locks,
113  _pimpl->locks.end() );
115  readPoolQueriesFromFile( file, boost::make_function_output_iterator(lout) );
116  }
117  else
118  MIL << "file not exist(or cannot be stat), no lock added." << endl;
119 
120 }
121 
122 void Locks::read( const Pathname& file )
123 {
124  MIL << "read locks from "<<file << endl;
125  PathInfo pinfo(file);
126  if ( pinfo.isExist() )
128  file, insert_iterator<LockList>(_pimpl->locks, _pimpl->locks.end()) );
129  else
130  MIL << "file not exist(or cannot be stat), no lock added." << endl;
131 }
132 
133 
134 void Locks::apply() const
135 {
136  DBG << "apply locks" << endl;
137  for_each(begin(), end(), ApplyLock());
138 }
139 
140 
141 void Locks::addLock( const PoolQuery& query )
142 {
143  MIL << "add new lock" << endl;
144  for_( it,query.begin(),query.end() )
145  {
146  PoolItem item(*it);
147  item.status().setLock(true,ResStatus::USER);
148  }
149  LockList::iterator i = find(_pimpl->toRemove.begin(),
150  _pimpl->toRemove.end(), query);
151  if ( i != _pimpl->toRemove.end() )
152  {
153  DBG << "query removed from toRemove" << endl;
154  _pimpl->toRemove.erase(i);
155  }
156  else
157  {
158  DBG << "query added as new" << endl;
159  _pimpl->toAdd.push_back( query );
160  }
161 }
162 
163 void Locks::addLock( const IdString& ident_r )
164 {
165  sat::Solvable::SplitIdent id(ident_r);
166  addLock(id.kind(),id.name());
167 }
168 
169 void Locks::addLock( const ResKind& kind_r, const C_Str & name_r )
170 {
171  addLock(kind_r,IdString(name_r));
172 }
173 
174 void Locks::addLock( const ResKind& kind_r, const IdString& name_r )
175 {
176  PoolQuery q;
178  q.addKind( kind_r );
179  q.setMatchExact();
180  q.setCaseSensitive(true);
181  DBG << "add lock by identifier" << endl;
182  addLock( q );
183 }
184 
185 void Locks::removeLock( const PoolQuery& query )
186 {
187  MIL << "remove lock" << endl;
188  for_( it,query.begin(),query.end() )
189  {
190  PoolItem item(*it);
191  item.status().setLock(false,ResStatus::USER);
192  }
193 
194  LockList::iterator i = find(_pimpl->toAdd.begin(),
195  _pimpl->toAdd.end(), query);
196  if ( i != _pimpl->toAdd.end() )
197  {
198  DBG << "query removed from added" << endl;
199  _pimpl->toAdd.erase(i);
200  }
201  else
202  {
203  DBG << "needed remove some old lock" << endl;
204  _pimpl->toRemove.push_back( query );
205  }
206 }
207 
208 void Locks::removeLock( const IdString& ident_r )
209 {
210  sat::Solvable::SplitIdent id(ident_r);
211  removeLock(id.kind(),id.name());
212 }
213 
214 void Locks::removeLock( const ResKind& kind_r, const C_Str & name_r )
215 {
216  removeLock(kind_r,IdString(name_r));
217 }
218 
219 void Locks::removeLock( const ResKind &kind_r, const IdString &name_r )
220 {
221  PoolQuery q;
223  q.addKind( kind_r );
224  q.setMatchExact();
225  q.setCaseSensitive(true);
226  DBG << "remove lock by Selectable" << endl;
227  removeLock(q);
228 }
229 
230 bool Locks::existEmpty() const
231 {
232  for_( it, _pimpl->locks.begin(), _pimpl->locks.end() )
233  {
234  if( it->empty() )
235  return true;
236  }
237 
238  return false;
239 }
240 
241 //handle locks during removing
243 private:
244  bool skip_rest;
245  size_t searched;
246  size_t all;
248 
249 public:
250  LocksCleanPredicate(size_t count, callback::SendReport<CleanEmptyLocksReport> &_report): skip_rest(false),searched(0),all(count), report(_report){}
251 
252  bool aborted(){ return skip_rest; }
253 
255  {
256  if( skip_rest )
257  return false;
258  searched++;
259  if( !q.empty() )
260  return false;
261 
262  if (!report->progress((100*searched)/all))
263  {
264  skip_rest = true;
265  return false;
266  }
267 
268  switch (report->execute(q))
269  {
272  skip_rest = true;
273  return false;
275  return true;
277  return false;
278  default:
279  WAR << "Unknown returned value. Callback have more value then"
280  << " this switch. Need correct handle all enum values." << std::endl;
281  }
282 
283  return false;
284  }
285 
286 };
287 
289 {
290  MIL << "cleaning of locks" << endl;
292  report->start();
293  size_t sum = _pimpl->locks.size();
294  LocksCleanPredicate p(sum, report);
295 
296  _pimpl->locks.remove_if(p);
297 
298  if( p.aborted() )
299  {
300  MIL << "cleaning aborted" << endl;
301  report->finish(CleanEmptyLocksReport::ABORTED);
302  }
303  else
304  {
305  report->finish(CleanEmptyLocksReport::NO_ERROR);
306 
307  }
308 
309  if ( sum != _pimpl->locks.size() ) //some locks has been removed
310  _pimpl->locksDirty = true;
311 }
312 
314 {
315 private:
316  std::set<sat::Solvable>& solvs;
317  const PoolQuery& query;
319  bool aborted_;
320 
321  //1 for subset of set, 2 only intersect, 0 for not intersect
322  int contains(const PoolQuery& q, std::set<sat::Solvable>& s)
323  {
324  bool intersect = false;
325  for_( it,q.begin(),q.end() )
326  {
327  if ( s.find(*it)!=s.end() )
328  {
329  intersect = true;
330  }
331  else
332  {
333  if (intersect)
334  return 2;
335  }
336  }
337  return intersect ? 1 : 0;
338  }
339 
340 public:
341  LocksRemovePredicate(std::set<sat::Solvable>& s, const PoolQuery& q,
343  : solvs(s), query(q),report(r),aborted_(false) {}
344 
345  bool operator()(const PoolQuery& q)
346  {
347  if (aborted())
348  return false;
349  if( q==query )
350  {//identical
351  DBG << "identical queries" << endl;
352  return true;
353  }
354 
356  switch( contains(q,solvs) )
357  {
358  case 0:
359  return false; //another lock
360  case 1:
362  break;
363  case 2:
365  break;
366  default:
367  return true;
368  }
369  MIL << "find conflict: " << cs << endl;
370  switch (report->conflict(q,cs))
371  {
373  aborted_ = true;
374  DBG << "abort merging" << endl;
375  return false;
377  DBG << "force delete" << endl;
378  return true;
380  DBG << "skip lock" << endl;
381  return false;
382  }
383  WAR << "should not reached, some state is missing" << endl;
384  return false;
385  }
386 
387  bool aborted(){ return aborted_; }
388 };
389 
391 {
392  MIL << "merging list old: " << locks.size()
393  << " to add: " << toAdd.size() << "to remove: " << toRemove.size() << endl;
394  for_(it,toRemove.begin(),toRemove.end())
395  {
396  std::set<sat::Solvable> s(it->begin(),it->end());
397  locks.remove_if(LocksRemovePredicate(s,*it, report));
398  }
399 
400  if (!report->progress())
401  return false;
402 
403  for_( it, toAdd.begin(), toAdd.end() )
404  {
405  if( std::find( locks.begin(), locks.end(), *it ) == locks.end() )
406  locks.push_back( *it );
407  }
408 
409  toAdd.clear();
410  toRemove.clear();
411 
412  return true;
413 }
414 
416 {
417  if( (_pimpl->toAdd.size() | _pimpl->toRemove.size())==0)
418  {
419  return; //nothing to merge
420  }
421 
423  report->start();
424  if (!_pimpl->mergeList(report))
425  {
426  report->finish(SavingLocksReport::ABORTED);
427  return;
428  }
429  DBG << "locks merged" << endl;
430  report->finish(SavingLocksReport::NO_ERROR);
431  _pimpl->locksDirty = true;
432 }
433 
434 void Locks::save( const Pathname& file )
435 {
436  if( ((_pimpl->toAdd.size() | _pimpl->toRemove.size())==0)
437  && !_pimpl->locksDirty )
438  {
439  DBG << "nothing changed in locks - no write to file" << endl;
440  return;
441  }
442 
444  report->start();
445 
446  if ((_pimpl->toAdd.size() | _pimpl->toRemove.size())!=0)
447  {
448  if (!_pimpl->mergeList(report))
449  {
450  report->finish(SavingLocksReport::ABORTED);
451  return;
452  }
453  }
454 
455  DBG << "writed "<< _pimpl->locks.size() << "locks" << endl;
456  writePoolQueriesToFile( file, _pimpl->locks.begin(), _pimpl->locks.end() );
457  report->finish(SavingLocksReport::NO_ERROR);
458 }
459 
461 {
462  size_type sum = size();
463  for_(it,_pimpl->locks.begin(),_pimpl->locks.end())
464  {
465  if ( find(_pimpl->locks.begin(),it,*it) != it )
466  _pimpl->locks.erase(it--); //-- to avoid using break iterator
467  }
468 
469  if (sum!=size())
470  _pimpl->locksDirty = true;
471 }
472 
473 } // ns zypp
LocksRemovePredicate(std::set< sat::Solvable > &s, const PoolQuery &q, callback::SendReport< SavingLocksReport > &r)
Definition: Locks.cc:341
void operator()(const PoolQuery &query) const
Definition: Locks.cc:74
#define MIL
Definition: Logger.h:47
void addAttribute(const sat::SolvAttr &attr, const std::string &value="")
Filter by the value of the specified attr attribute.
Definition: PoolQuery.cc:795
LockList toAdd
Definition: Locks.cc:49
void operator()(const PoolQuery &query) const
Definition: Locks.cc:96
void removeEmpty()
Call callback for each empty lock.
Definition: Locks.cc:288
void readPoolQueriesFromFile(const zypp::filesystem::Pathname &file, OutputIterator out)
sends to output iterator all queries readed from file.
LockingOutputIterator(OutputIterator &out_)
Definition: Locks.cc:92
const_iterator begin() const
Definition: Locks.cc:60
void setCaseSensitive(bool value=true)
Turn case sentitivity on or off (unsets or sets SEARCH_NOCASE flag).
Definition: PoolQuery.cc:908
Access to the sat-pools string space.
Definition: IdString.h:39
cleaning aborted by user
void addKind(const ResKind &kind)
Filter by selectable kind.
Definition: PoolQuery.cc:789
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
delete conflicted lock
LockList::size_type size() const
Definition: Locks.cc:66
RW_pointer< Impl, rw_pointer::Scoped< Impl > > _pimpl
Definition: Locks.h:148
void addLock(const PoolQuery &query)
TODO add: toBeAdded{Begin,End,Size,Empty} toBeRemoved{Begin,End,Size,Empty}.
Definition: Locks.cc:141
std::string asString() const
Conversion to std::string
Definition: IdString.h:83
Singleton class which manipulate with locks file and apply locks on pool.
Definition: Locks.h:18
LockList locks
Definition: Locks.cc:48
locks lock some file and unlocking lock unlock only part of iti, so removing old lock can unlock more...
void apply() const
Applies locks in stable list (locks which is not changed during session).
Definition: Locks.cc:134
std::list< PoolQuery > LockList
Definition: Locks.h:21
LockList toRemove
Definition: Locks.cc:50
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
Definition: PoolItem.cc:285
void removeDuplicates()
Delete all query duplicate in loaded locks.
Definition: Locks.cc:460
bool empty() const
Definition: Locks.cc:69
Convenience char* constructible from std::string and char*, it maps (char*)0 to an empty string...
Definition: String.h:97
void merge()
Merges toAdd and ToRemove list to stable list.
Definition: Locks.cc:415
cleaning aborted by user
#define WAR
Definition: Logger.h:48
const PoolQuery & query
Definition: Locks.cc:317
including fstream is not hell here because this header only included by implementation file...
ResStatus & status() const
Returns the current status.
Definition: PoolItem.cc:246
void writePoolQueriesToFile(const zypp::filesystem::Pathname &file, InputIterator begin, InputIterator end)
Writes all queries from begin to end.
locks lock same item in pool but his parameters is different
bool setLock(bool toLock_r, TransactByValue causer_r)
Apply a lock (prevent transaction).
Definition: ResStatus.h:376
static const SolvAttr name
Definition: SolvAttr.h:52
LocksCleanPredicate(size_t count, callback::SendReport< CleanEmptyLocksReport > &_report)
Definition: Locks.cc:250
bool mergeList(callback::SendReport< SavingLocksReport > &report)
Definition: Locks.cc:390
const_iterator end() const
Definition: Locks.cc:63
void save(const Pathname &file=ZConfig::instance().locksFile())
Merges toAdd and ToRemove list to stable list and save that stable list to file.
Definition: Locks.cc:434
void readAndApply(const Pathname &file=ZConfig::instance().locksFile())
Optimalized version of read and apply.
Definition: Locks.cc:106
SolvableIdType size_type
Definition: PoolMember.h:99
bool locksDirty
Definition: Locks.cc:51
bool operator()(PoolQuery &q)
Definition: Locks.cc:254
Meta-data query API.
Definition: PoolQuery.h:90
bool operator()(const PoolQuery &q)
Definition: Locks.cc:345
bool empty() const
Whether the result is empty.
Definition: PoolQuery.cc:925
void setMatchExact()
Set to match exact string instead of substring.
Definition: PoolQuery.cc:856
OutputIterator & out
Definition: Locks.cc:103
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:176
Helper that splits an identifier into kind and name or vice versa.
Definition: Solvable.h:264
abort and return error
Reference to a PoolItem connecting ResObject and ResStatus.
Definition: PoolItem.h:50
LockList::size_type size_type
Definition: Locks.h:23
const_iterator begin() const
Query result accessers.
Definition: PoolQuery.cc:1643
ConflictState
type of conflict of old and new lock
int contains(const PoolQuery &q, std::set< sat::Solvable > &s)
Definition: Locks.cc:322
callback::SendReport< SavingLocksReport > & report
Definition: Locks.cc:318
void read(const Pathname &file=ZConfig::instance().locksFile())
Read locks from file to list of stable locks (locks which is not changed during session) ...
Definition: Locks.cc:122
void removeLock(const PoolQuery &query)
unlocks by result of query and add to toRemove.
Definition: Locks.cc:185
callback::SendReport< CleanEmptyLocksReport > & report
Definition: Locks.cc:247
const_iterator end() const
An iterator pointing to the end of the query result.
Definition: PoolQuery.h:604
LockList::const_iterator const_iterator
Definition: Locks.h:22
std::set< sat::Solvable > & solvs
Definition: Locks.cc:316
Resolvable kinds.
Definition: ResKind.h:32
bool existEmpty() const
Gets true if some lock doesn't lock any object in pool This can happen e.g.
Definition: Locks.cc:230
iterator that takes lock, lock all solvables from query and send query to output iterator ...
Definition: Locks.cc:90
#define DBG
Definition: Logger.h:46