libzypp  13.10.6
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  q.requireAll();
227  DBG << "remove lock by selectactable" << endl;
228  removeLock(q);
229 }
230 
231 bool Locks::existEmpty() const
232 {
233  for_( it, _pimpl->locks.begin(), _pimpl->locks.end() )
234  {
235  if( it->empty() )
236  return true;
237  }
238 
239  return false;
240 }
241 
242 //handle locks during removing
244 private:
245  bool skip_rest;
246  size_t searched;
247  size_t all;
249 
250 public:
251  LocksCleanPredicate(size_t count, callback::SendReport<CleanEmptyLocksReport> &_report): skip_rest(false),searched(0),all(count), report(_report){}
252 
253  bool aborted(){ return skip_rest; }
254 
256  {
257  if( skip_rest )
258  return false;
259  searched++;
260  if( !q.empty() )
261  return false;
262 
263  if (!report->progress((100*searched)/all))
264  {
265  skip_rest = true;
266  return false;
267  }
268 
269  switch (report->execute(q))
270  {
273  skip_rest = true;
274  return false;
276  return true;
278  return false;
279  default:
280  WAR << "Unknown returned value. Callback have more value then"
281  << " this switch. Need correct handle all enum values." << std::endl;
282  }
283 
284  return false;
285  }
286 
287 };
288 
290 {
291  MIL << "cleaning of locks" << endl;
293  report->start();
294  size_t sum = _pimpl->locks.size();
295  LocksCleanPredicate p(sum, report);
296 
297  _pimpl->locks.remove_if(p);
298 
299  if( p.aborted() )
300  {
301  MIL << "cleaning aborted" << endl;
302  report->finish(CleanEmptyLocksReport::ABORTED);
303  }
304  else
305  {
306  report->finish(CleanEmptyLocksReport::NO_ERROR);
307 
308  }
309 
310  if ( sum != _pimpl->locks.size() ) //some locks has been removed
311  _pimpl->locksDirty = true;
312 }
313 
315 {
316 private:
317  std::set<sat::Solvable>& solvs;
318  const PoolQuery& query;
320  bool aborted_;
321 
322  //1 for subset of set, 2 only intersect, 0 for not intersect
323  int contains(const PoolQuery& q, std::set<sat::Solvable>& s)
324  {
325  bool intersect = false;
326  for_( it,q.begin(),q.end() )
327  {
328  if ( s.find(*it)!=s.end() )
329  {
330  intersect = true;
331  }
332  else
333  {
334  if (intersect)
335  return 2;
336  }
337  }
338  return intersect ? 1 : 0;
339  }
340 
341 public:
342  LocksRemovePredicate(std::set<sat::Solvable>& s, const PoolQuery& q,
344  : solvs(s), query(q),report(r),aborted_(false) {}
345 
346  bool operator()(const PoolQuery& q)
347  {
348  if (aborted())
349  return false;
350  if( q==query )
351  {//identical
352  DBG << "identical queries" << endl;
353  return true;
354  }
355 
357  switch( contains(q,solvs) )
358  {
359  case 0:
360  return false; //another lock
361  case 1:
363  break;
364  case 2:
366  break;
367  default:
368  return true;
369  }
370  MIL << "find conflict: " << cs << endl;
371  switch (report->conflict(q,cs))
372  {
374  aborted_ = true;
375  DBG << "abort merging" << endl;
376  return false;
378  DBG << "force delete" << endl;
379  return true;
381  DBG << "skip lock" << endl;
382  return false;
383  }
384  WAR << "should not reached, some state is missing" << endl;
385  return false;
386  }
387 
388  bool aborted(){ return aborted_; }
389 };
390 
392 {
393  MIL << "merging list old: " << locks.size()
394  << " to add: " << toAdd.size() << "to remove: " << toRemove.size() << endl;
395  for_(it,toRemove.begin(),toRemove.end())
396  {
397  std::set<sat::Solvable> s(it->begin(),it->end());
398  locks.remove_if(LocksRemovePredicate(s,*it, report));
399  }
400 
401  if (!report->progress())
402  return false;
403 
404  for_( it, toAdd.begin(), toAdd.end() )
405  {
406  if( std::find( locks.begin(), locks.end(), *it ) == locks.end() )
407  locks.push_back( *it );
408  }
409 
410  toAdd.clear();
411  toRemove.clear();
412 
413  return true;
414 }
415 
417 {
418  if( (_pimpl->toAdd.size() | _pimpl->toRemove.size())==0)
419  {
420  return; //nothing to merge
421  }
422 
424  report->start();
425  if (!_pimpl->mergeList(report))
426  {
427  report->finish(SavingLocksReport::ABORTED);
428  return;
429  }
430  DBG << "locks merged" << endl;
431  report->finish(SavingLocksReport::NO_ERROR);
432  _pimpl->locksDirty = true;
433 }
434 
435 void Locks::save( const Pathname& file )
436 {
437  if( ((_pimpl->toAdd.size() | _pimpl->toRemove.size())==0)
438  && !_pimpl->locksDirty )
439  {
440  DBG << "nothing changed in locks - no write to file" << endl;
441  return;
442  }
443 
445  report->start();
446 
447  if ((_pimpl->toAdd.size() | _pimpl->toRemove.size())!=0)
448  {
449  if (!_pimpl->mergeList(report))
450  {
451  report->finish(SavingLocksReport::ABORTED);
452  return;
453  }
454  }
455 
456  DBG << "writed "<< _pimpl->locks.size() << "locks" << endl;
457  writePoolQueriesToFile( file, _pimpl->locks.begin(), _pimpl->locks.end() );
458  report->finish(SavingLocksReport::NO_ERROR);
459 }
460 
462 {
463  size_type sum = size();
464  for_(it,_pimpl->locks.begin(),_pimpl->locks.end())
465  {
466  if ( find(_pimpl->locks.begin(),it,*it) != it )
467  _pimpl->locks.erase(it--); //-- to avoid using break iterator
468  }
469 
470  if (sum!=size())
471  _pimpl->locksDirty = true;
472 }
473 
474 } // ns zypp
LocksRemovePredicate(std::set< sat::Solvable > &s, const PoolQuery &q, callback::SendReport< SavingLocksReport > &r)
Definition: Locks.cc:342
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:854
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:289
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:975
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:848
#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
bool requireAll() const
Whether all values added via addString() or addAttribute() are required to match the values of the re...
Definition: PoolQuery.cc:991
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:280
void removeDuplicates()
Delete all query duplicate in loaded locks.
Definition: Locks.cc:461
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:81
void merge()
Merges toAdd and ToRemove list to stable list.
Definition: Locks.cc:416
cleaning aborted by user
#define WAR
Definition: Logger.h:48
const PoolQuery & query
Definition: Locks.cc:318
including fstream is not hell here because this header only included by implementation file...
ResStatus & status() const
Returns the current status.
Definition: PoolItem.cc:241
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:251
bool mergeList(callback::SendReport< SavingLocksReport > &report)
Definition: Locks.cc:391
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:435
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:255
Meta-data query API.
Definition: PoolQuery.h:90
bool operator()(const PoolQuery &q)
Definition: Locks.cc:346
bool empty() const
Whether the result is empty.
Definition: PoolQuery.cc:997
void setMatchExact()
Set to match exact string instead of substring.
Definition: PoolQuery.cc:915
OutputIterator & out
Definition: Locks.cc:103
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:178
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:1735
ConflictState
type of conflict of old and new lock
int contains(const PoolQuery &q, std::set< sat::Solvable > &s)
Definition: Locks.cc:323
callback::SendReport< SavingLocksReport > & report
Definition: Locks.cc:319
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:248
const_iterator end() const
An iterator pointing to the end of the query result.
Definition: PoolQuery.h:616
LockList::const_iterator const_iterator
Definition: Locks.h:22
std::set< sat::Solvable > & solvs
Definition: Locks.cc:317
Resolvable kinds.
Definition: ResKind.h:35
bool existEmpty() const
Gets true if some lock doesn&#39;t lock any object in pool This can happen e.g.
Definition: Locks.cc:231
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