libzypp  16.17.4
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 std::endl;
33 
34 namespace zypp
35 {
36 
38 {
39  static Locks _instance;
40  return _instance;
41 }
42 
44 {
45 public:
49  bool locksDirty;
50 
52 
53  Impl():locksDirty(false){}
54 };
55 
57 
59 { return _pimpl->locks.begin(); }
60 
62 { return _pimpl->locks.end(); }
63 
65 { return _pimpl->locks.size(); }
66 
67 bool Locks::empty() const
68 { return _pimpl->locks.empty(); }
69 
70 struct ApplyLock
71 {
72  void operator()(const PoolQuery& query) const
73  {
74  for ( const PoolItem & item : query.poolItem() )
75  {
76  item.status().setLock(true,ResStatus::USER);
77  DBG << "lock "<< item.name();
78  }
79  }
80 };
81 
86 template <class OutputIterator>
88 {
89  LockingOutputIterator(OutputIterator& out_)
90  : out(out_)
91  {}
92 
93  void operator()(const PoolQuery& query) const
94  {
95  ApplyLock a;a(query);
96  *out++ = query;
97  }
98 
99  private:
100  OutputIterator& out;
101 };
102 
103 void Locks::readAndApply( const Pathname& file )
104 {
105  MIL << "read and apply locks from "<<file << endl;
106  PathInfo pinfo(file);
107  if ( pinfo.isExist() )
108  {
109  std::insert_iterator<LockList> ii( _pimpl->locks, _pimpl->locks.end() );
111  readPoolQueriesFromFile( file, boost::make_function_output_iterator(lout) );
112  }
113  else
114  MIL << "file not exist(or cannot be stat), no lock added." << endl;
115 
116 }
117 
118 void Locks::read( const Pathname& file )
119 {
120  MIL << "read locks from "<<file << endl;
121  PathInfo pinfo(file);
122  if ( pinfo.isExist() )
123  readPoolQueriesFromFile( file, std::insert_iterator<LockList>(_pimpl->locks, _pimpl->locks.end()) );
124  else
125  MIL << "file not exist(or cannot be stat), no lock added." << endl;
126 }
127 
128 
129 void Locks::apply() const
130 {
131  DBG << "apply locks" << endl;
132  for_each(begin(), end(), ApplyLock());
133 }
134 
135 
136 void Locks::addLock( const PoolQuery& query )
137 {
138  MIL << "add new lock" << endl;
139  for_( it,query.begin(),query.end() )
140  {
141  PoolItem item(*it);
142  item.status().setLock(true,ResStatus::USER);
143  }
144  LockList::iterator i = find(_pimpl->toRemove.begin(),
145  _pimpl->toRemove.end(), query);
146  if ( i != _pimpl->toRemove.end() )
147  {
148  DBG << "query removed from toRemove" << endl;
149  _pimpl->toRemove.erase(i);
150  }
151  else
152  {
153  DBG << "query added as new" << endl;
154  _pimpl->toAdd.push_back( query );
155  }
156 }
157 
158 void Locks::addLock( const IdString& ident_r )
159 {
160  sat::Solvable::SplitIdent id(ident_r);
161  addLock(id.kind(),id.name());
162 }
163 
164 void Locks::addLock( const ResKind& kind_r, const C_Str & name_r )
165 {
166  addLock(kind_r,IdString(name_r));
167 }
168 
169 void Locks::addLock( const ResKind& kind_r, const IdString& name_r )
170 {
171  PoolQuery q;
173  q.addKind( kind_r );
174  q.setMatchExact();
175  q.setCaseSensitive(true);
176  DBG << "add lock by identifier" << endl;
177  addLock( q );
178 }
179 
180 void Locks::removeLock( const PoolQuery& query )
181 {
182  MIL << "remove lock" << endl;
183  for_( it,query.begin(),query.end() )
184  {
185  PoolItem item(*it);
186  item.status().setLock(false,ResStatus::USER);
187  }
188 
189  LockList::iterator i = find(_pimpl->toAdd.begin(),
190  _pimpl->toAdd.end(), query);
191  if ( i != _pimpl->toAdd.end() )
192  {
193  DBG << "query removed from added" << endl;
194  _pimpl->toAdd.erase(i);
195  }
196  else
197  {
198  DBG << "needed remove some old lock" << endl;
199  _pimpl->toRemove.push_back( query );
200  }
201 }
202 
203 void Locks::removeLock( const IdString& ident_r )
204 {
205  sat::Solvable::SplitIdent id(ident_r);
206  removeLock(id.kind(),id.name());
207 }
208 
209 void Locks::removeLock( const ResKind& kind_r, const C_Str & name_r )
210 {
211  removeLock(kind_r,IdString(name_r));
212 }
213 
214 void Locks::removeLock( const ResKind &kind_r, const IdString &name_r )
215 {
216  PoolQuery q;
218  q.addKind( kind_r );
219  q.setMatchExact();
220  q.setCaseSensitive(true);
221  q.requireAll();
222  DBG << "remove lock by selectactable" << endl;
223  removeLock(q);
224 }
225 
226 bool Locks::existEmpty() const
227 {
228  for_( it, _pimpl->locks.begin(), _pimpl->locks.end() )
229  {
230  if( it->empty() )
231  return true;
232  }
233 
234  return false;
235 }
236 
237 //handle locks during removing
239 private:
240  bool skip_rest;
241  size_t searched;
242  size_t all;
244 
245 public:
246  LocksCleanPredicate(size_t count, callback::SendReport<CleanEmptyLocksReport> &_report): skip_rest(false),searched(0),all(count), report(_report){}
247 
248  bool aborted(){ return skip_rest; }
249 
251  {
252  if( skip_rest )
253  return false;
254  searched++;
255  if( !q.empty() )
256  return false;
257 
258  if (!report->progress((100*searched)/all))
259  {
260  skip_rest = true;
261  return false;
262  }
263 
264  switch (report->execute(q))
265  {
267  report->finish(CleanEmptyLocksReport::ABORTED);
268  skip_rest = true;
269  return false;
271  return true;
273  return false;
274  default:
275  WAR << "Unknown returned value. Callback have more value then"
276  << " this switch. Need correct handle all enum values." << std::endl;
277  }
278 
279  return false;
280  }
281 
282 };
283 
285 {
286  MIL << "cleaning of locks" << endl;
288  report->start();
289  size_t sum = _pimpl->locks.size();
290  LocksCleanPredicate p(sum, report);
291 
292  _pimpl->locks.remove_if(p);
293 
294  if( p.aborted() )
295  {
296  MIL << "cleaning aborted" << endl;
297  report->finish(CleanEmptyLocksReport::ABORTED);
298  }
299  else
300  {
301  report->finish(CleanEmptyLocksReport::NO_ERROR);
302 
303  }
304 
305  if ( sum != _pimpl->locks.size() ) //some locks has been removed
306  _pimpl->locksDirty = true;
307 }
308 
310 {
311 private:
312  std::set<sat::Solvable>& solvs;
313  const PoolQuery& query;
315  bool aborted_;
316 
317  //1 for subset of set, 2 only intersect, 0 for not intersect
318  int contains(const PoolQuery& q, std::set<sat::Solvable>& s)
319  {
320  bool intersect = false;
321  for_( it,q.begin(),q.end() )
322  {
323  if ( s.find(*it)!=s.end() )
324  {
325  intersect = true;
326  }
327  else
328  {
329  if (intersect)
330  return 2;
331  }
332  }
333  return intersect ? 1 : 0;
334  }
335 
336 public:
337  LocksRemovePredicate(std::set<sat::Solvable>& s, const PoolQuery& q,
339  : solvs(s), query(q),report(r),aborted_(false) {}
340 
341  bool operator()(const PoolQuery& q)
342  {
343  if (aborted())
344  return false;
345  if( q==query )
346  {//identical
347  DBG << "identical queries" << endl;
348  return true;
349  }
350 
352  switch( contains(q,solvs) )
353  {
354  case 0:
355  return false; //another lock
356  case 1:
358  break;
359  case 2:
361  break;
362  default:
363  return true;
364  }
365  MIL << "find conflict: " << cs << endl;
366  switch (report->conflict(q,cs))
367  {
369  aborted_ = true;
370  DBG << "abort merging" << endl;
371  return false;
373  DBG << "force delete" << endl;
374  return true;
376  DBG << "skip lock" << endl;
377  return false;
378  }
379  WAR << "should not reached, some state is missing" << endl;
380  return false;
381  }
382 
383  bool aborted(){ return aborted_; }
384 };
385 
387 {
388  MIL << "merging list old: " << locks.size()
389  << " to add: " << toAdd.size() << "to remove: " << toRemove.size() << endl;
390  for_(it,toRemove.begin(),toRemove.end())
391  {
392  std::set<sat::Solvable> s(it->begin(),it->end());
393  locks.remove_if(LocksRemovePredicate(s,*it, report));
394  }
395 
396  if (!report->progress())
397  return false;
398 
399  for_( it, toAdd.begin(), toAdd.end() )
400  {
401  if( std::find( locks.begin(), locks.end(), *it ) == locks.end() )
402  locks.push_back( *it );
403  }
404 
405  toAdd.clear();
406  toRemove.clear();
407 
408  return true;
409 }
410 
412 {
413  if( (_pimpl->toAdd.size() | _pimpl->toRemove.size())==0)
414  {
415  return; //nothing to merge
416  }
417 
419  report->start();
420  if (!_pimpl->mergeList(report))
421  {
422  report->finish(SavingLocksReport::ABORTED);
423  return;
424  }
425  DBG << "locks merged" << endl;
426  report->finish(SavingLocksReport::NO_ERROR);
427  _pimpl->locksDirty = true;
428 }
429 
430 void Locks::save( const Pathname& file )
431 {
432  if( ((_pimpl->toAdd.size() | _pimpl->toRemove.size())==0)
433  && !_pimpl->locksDirty )
434  {
435  DBG << "nothing changed in locks - no write to file" << endl;
436  return;
437  }
438 
440  report->start();
441 
442  if ((_pimpl->toAdd.size() | _pimpl->toRemove.size())!=0)
443  {
444  if (!_pimpl->mergeList(report))
445  {
446  report->finish(SavingLocksReport::ABORTED);
447  return;
448  }
449  }
450 
451  DBG << "writed "<< _pimpl->locks.size() << "locks" << endl;
452  writePoolQueriesToFile( file, _pimpl->locks.begin(), _pimpl->locks.end() );
453  report->finish(SavingLocksReport::NO_ERROR);
454 }
455 
457 {
458  size_type sum = size();
459  for_(it,_pimpl->locks.begin(),_pimpl->locks.end())
460  {
461  if ( find(_pimpl->locks.begin(),it,*it) != it )
462  _pimpl->locks.erase(it--); //-- to avoid using break iterator
463  }
464 
465  if (sum!=size())
466  _pimpl->locksDirty = true;
467 }
468 
469 } // ns zypp
LocksRemovePredicate(std::set< sat::Solvable > &s, const PoolQuery &q, callback::SendReport< SavingLocksReport > &r)
Definition: Locks.cc:337
void operator()(const PoolQuery &query) const
Definition: Locks.cc:72
#define MIL
Definition: Logger.h:64
bool contains(const C_Str &str_r, const C_Str &val_r)
Locate substring case sensitive.
Definition: String.h:965
void addAttribute(const sat::SolvAttr &attr, const std::string &value="")
Filter by the value of the specified attr attribute.
Definition: PoolQuery.cc:869
LockList toAdd
Definition: Locks.cc:47
void operator()(const PoolQuery &query) const
Definition: Locks.cc:93
void removeEmpty()
Call callback for each empty lock.
Definition: Locks.cc:284
LockingOutputIterator(OutputIterator &out_)
Definition: Locks.cc:89
const_iterator begin() const
Definition: Locks.cc:58
void setCaseSensitive(bool value=true)
Turn case sentitivity on or off (unsets or sets SEARCH_NOCASE flag).
Definition: PoolQuery.cc:1002
Access to the sat-pools string space.
Definition: IdString.h:41
cleaning aborted by user
void addKind(const ResKind &kind)
Filter by selectable kind.
Definition: PoolQuery.cc:863
#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:64
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:136
std::string asString() const
Conversion to std::string
Definition: IdString.h:91
bool requireAll() const
Whether all values added via addString() or addAttribute() are required to match the values of the re...
Definition: PoolQuery.cc:1018
Singleton class which manipulate with locks file and apply locks on pool.
Definition: Locks.h:18
LockList locks
Definition: Locks.cc:46
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:129
std::list< PoolQuery > LockList
Definition: Locks.h:21
LockList toRemove
Definition: Locks.cc:48
void removeDuplicates()
Delete all query duplicate in loaded locks.
Definition: Locks.cc:456
bool empty() const
Definition: Locks.cc:67
static Locks & instance()
Gets instance of this class.
Definition: Locks.cc:37
Convenience char* constructible from std::string and char*, it maps (char*)0 to an empty string...
Definition: String.h:90
void merge()
Merges toAdd and ToRemove list to stable list.
Definition: Locks.cc:411
cleaning aborted by user
#define WAR
Definition: Logger.h:65
const PoolQuery & query
Definition: Locks.cc:313
ResStatus & status() const
Returns the current status.
Definition: PoolItem.cc:204
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:379
Iterable< PoolItem_iterator > poolItem() const
static const SolvAttr name
Definition: SolvAttr.h:52
LocksCleanPredicate(size_t count, callback::SendReport< CleanEmptyLocksReport > &_report)
Definition: Locks.cc:246
bool mergeList(callback::SendReport< SavingLocksReport > &report)
Definition: Locks.cc:386
const_iterator end() const
Definition: Locks.cc:61
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:430
void readAndApply(const Pathname &file=ZConfig::instance().locksFile())
Optimalized version of read and apply.
Definition: Locks.cc:103
SolvableIdType size_type
Definition: PoolMember.h:126
bool locksDirty
Definition: Locks.cc:49
bool operator()(PoolQuery &q)
Definition: Locks.cc:250
Meta-data query API.
Definition: PoolQuery.h:90
bool operator()(const PoolQuery &q)
Definition: Locks.cc:341
bool empty() const
Whether the result is empty.
Definition: PoolQuery.cc:1024
void setMatchExact()
Set to match exact string instead of substring.
Definition: PoolQuery.cc:942
OutputIterator & out
Definition: Locks.cc:100
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:199
Helper that splits an identifier into kind and name or vice versa.
Definition: Solvable.h:301
abort and return error
Combining sat::Solvable 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:1782
ConflictState
type of conflict of old and new lock
int contains(const PoolQuery &q, std::set< sat::Solvable > &s)
Definition: Locks.cc:318
callback::SendReport< SavingLocksReport > & report
Definition: Locks.cc:314
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:118
void removeLock(const PoolQuery &query)
unlocks by result of query and add to toRemove.
Definition: Locks.cc:180
callback::SendReport< CleanEmptyLocksReport > & report
Definition: Locks.cc:243
const_iterator end() const
An iterator pointing to the end of the query result.
Definition: PoolQuery.h:623
LockList::const_iterator const_iterator
Definition: Locks.h:22
std::set< sat::Solvable > & solvs
Definition: Locks.cc:312
Resolvable kinds.
Definition: ResKind.h:32
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
bool existEmpty() const
Gets true if some lock doesn&#39;t lock any object in pool This can happen e.g.
Definition: Locks.cc:226
iterator that takes lock, lock all solvables from query and send query to output iterator ...
Definition: Locks.cc:87
#define DBG
Definition: Logger.h:63