libzypp  16.6.1
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
#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:854
LockList toAdd
Definition: Locks.cc:47
void removeEmpty()
Call callback for each empty lock.
Definition: Locks.cc:284
void operator()(const PoolQuery &query) const
Definition: Locks.cc:72
LockingOutputIterator(OutputIterator &out_)
Definition: Locks.cc:89
ResStatus & status() const
Returns the current status.
Definition: PoolItem.cc:204
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
LockList::size_type size() const
Definition: Locks.cc:64
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:41
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
const_iterator begin() const
Definition: Locks.cc:58
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
void operator()(const PoolQuery &query) const
Definition: Locks.cc:93
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...
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
const_iterator end() const
Definition: Locks.cc:61
void apply() const
Applies locks in stable list (locks which is not changed during session).
Definition: Locks.cc:129
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
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
const_iterator begin() const
Query result accessers.
Definition: PoolQuery.cc:1735
#define WAR
Definition: Logger.h:65
const PoolQuery & query
Definition: Locks.cc:313
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
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
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
const_iterator end() const
An iterator pointing to the end of the query result.
Definition: PoolQuery.h:616
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 empty() const
Definition: Locks.cc:67
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
void setMatchExact()
Set to match exact string instead of substring.
Definition: PoolQuery.cc:915
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:298
abort and return error
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
bool empty() const
Whether the result is empty.
Definition: PoolQuery.cc:997
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:50
LockList::size_type size_type
Definition: Locks.h:23
std::string asString() const
Conversion to std::string
Definition: IdString.h:91
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
Iterable< PoolItem_iterator > poolItem() const
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 requireAll() const
Whether all values added via addString() or addAttribute() are required to match the values of the re...
Definition: PoolQuery.cc:991
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