Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / Locks.cc
index b734851..721a1cc 100644 (file)
@@ -11,6 +11,7 @@
 #include <fstream>
 #include <boost/function.hpp>
 #include <boost/function_output_iterator.hpp>
+#include <algorithm>
 
 #include "zypp/base/Regex.h"
 #include "zypp/base/String.h"
@@ -20,6 +21,7 @@
 #include "zypp/PoolQueryUtil.tcc"
 #include "zypp/ZYppCallbacks.h"
 #include "zypp/sat/SolvAttr.h"
+#include "zypp/sat/Solvable.h"
 #include "zypp/PathInfo.h"
 
 #undef ZYPP_BASE_LOGGER_LOGGROUP
@@ -33,8 +35,6 @@ using namespace zypp::str;
 
 namespace zypp
 {
-namespace locks
-{
 
 Locks& Locks::instance()
 {
@@ -45,16 +45,43 @@ Locks& Locks::instance()
 class Locks::Impl
 {
 public:
-  std::list<PoolQuery> locks;
-  std::list<PoolQuery> toAdd;
-  std::list<PoolQuery> toRemove;
+  LockList locks;
+  LockList toAdd;
+  LockList toRemove;
+  bool     locksDirty;
 
   bool mergeList(callback::SendReport<SavingLocksReport>& report);
   
+  Impl():locksDirty(false){}
 };
 
 Locks::Locks() : _pimpl(new Impl){}
 
+Locks::const_iterator Locks::begin() const
+{ return _pimpl->locks.begin(); }
+
+Locks::const_iterator Locks::end() const
+{ return _pimpl->locks.end(); }
+
+Locks::LockList::size_type Locks::size() const
+{ return _pimpl->locks.size(); }
+
+bool Locks::empty() const
+{ return _pimpl->locks.empty(); }
+
+struct ApplyLock
+{
+  void operator()(const PoolQuery& query) const
+  {
+    for_( it,query.begin(),query.end() )
+    {
+      PoolItem item(*it);
+      item.status().setLock(true,ResStatus::USER);
+      DBG << "lock "<< item.resolvable()->name();
+    }
+  }
+};
+
 /**
  * iterator that takes lock, lock all solvables from query 
  * and send query to output iterator
@@ -68,35 +95,58 @@ struct LockingOutputIterator
 
   void operator()(const PoolQuery& query) const
   {
-    for_( it,query.begin(),query.end() )
-    {
-      PoolItem item(*it);
-      item.status().setLock(true,ResStatus::USER);
-    }
-    
+    ApplyLock a;a(query);
     *out++ = query;
   }
   
   private:
   OutputIterator& out;
- };
+};
+
+void Locks::readAndApply( const Pathname& file )
+{
+  MIL << "read and apply locks from "<<file << endl;
+  PathInfo pinfo(file);
+  if ( pinfo.isExist() )
+  {
+    insert_iterator<LockList> ii( _pimpl->locks,
+        _pimpl->locks.end() );
+    LockingOutputIterator<insert_iterator<LockList> > lout(ii);
+    readPoolQueriesFromFile( file, boost::make_function_output_iterator(lout) );
+  }
+  else
+    MIL << "file not exist(or cannot be stat), no lock added." << endl;
+
+}
 
-void Locks::loadLocks( const Pathname& file )
+void Locks::read( const Pathname& file )
 {
-  insert_iterator<std::list<PoolQuery> > ii( _pimpl->locks,
-      _pimpl->locks.end() );
-  LockingOutputIterator<insert_iterator<std::list<PoolQuery> > > lout(ii);
-  readPoolQueriesFromFile( file, boost::make_function_output_iterator(lout) );
+  MIL << "read locks from "<<file << endl;
+  PathInfo pinfo(file);
+  if ( pinfo.isExist() )
+    readPoolQueriesFromFile(
+       file, insert_iterator<LockList>(_pimpl->locks, _pimpl->locks.end()) );
+  else 
+    MIL << "file not exist(or cannot be stat), no lock added." << endl;
+}
+
+
+void Locks::apply() const
+{ 
+  DBG << "apply locks" << endl;
+  for_each(begin(), end(), ApplyLock());
 }
 
+
 void Locks::addLock( const PoolQuery& query )
 {
+  MIL << "add new lock" << endl;
   for_( it,query.begin(),query.end() )
   {
     PoolItem item(*it);
     item.status().setLock(true,ResStatus::USER);
   }
-  std::list<PoolQuery>::iterator i = find(_pimpl->toRemove.begin(),
+  LockList::iterator i = find(_pimpl->toRemove.begin(),
     _pimpl->toRemove.end(), query);
   if ( i != _pimpl->toRemove.end() )
   {
@@ -110,26 +160,38 @@ void Locks::addLock( const PoolQuery& query )
   }
 }
 
-void Locks::addLock(const ui::Selectable& selectable)
+void Locks::addLock( const IdString& ident_r )
+{
+  sat::Solvable::SplitIdent id(ident_r);
+  addLock(id.kind(),id.name());
+}
+
+void Locks::addLock( const ResKind& kind_r, const C_Str & name_r )
+{
+  addLock(kind_r,IdString(name_r));
+}
+
+void Locks::addLock( const ResKind& kind_r, const IdString& name_r )
 {
   PoolQuery q;
-  q.addAttribute( sat::SolvAttr::name,selectable.name() );
-  q.addKind( selectable.kind() );
+  q.addAttribute( sat::SolvAttr::name,name_r.asString() );
+  q.addKind( kind_r );
   q.setMatchExact();
   q.setCaseSensitive(true);
-  q.requireAll();
+  DBG << "add lock by identifier" << endl;
   addLock( q );
 }
 
-void Locks::unlock( const PoolQuery& query )
+void Locks::removeLock( const PoolQuery& query )
 {
+  MIL << "remove lock" << endl;
   for_( it,query.begin(),query.end() )
   {
     PoolItem item(*it);
     item.status().setLock(false,ResStatus::USER);
   }
   
-  std::list<PoolQuery>::iterator i = find(_pimpl->toAdd.begin(),
+  LockList::iterator i = find(_pimpl->toAdd.begin(),
     _pimpl->toAdd.end(), query);
   if ( i != _pimpl->toAdd.end() )
   {
@@ -143,18 +205,30 @@ void Locks::unlock( const PoolQuery& query )
   }
 }
 
-void Locks::unlock( const ui::Selectable& s )
+void Locks::removeLock( const IdString& ident_r )
+{
+  sat::Solvable::SplitIdent id(ident_r);
+  removeLock(id.kind(),id.name());
+}
+
+void Locks::removeLock( const ResKind& kind_r, const C_Str & name_r )
+{
+  removeLock(kind_r,IdString(name_r));
+}
+
+void Locks::removeLock( const ResKind &kind_r, const IdString &name_r )
 {
   PoolQuery q;
-  q.addAttribute( sat::SolvAttr::name,s.name() );
-  q.addKind( s.kind() );
+  q.addAttribute( sat::SolvAttr::name,name_r.asString() );
+  q.addKind( kind_r );
   q.setMatchExact();
   q.setCaseSensitive(true);
   q.requireAll();
-  unlock(q);
+  DBG << "remove lock by selectactable" << endl;
+  removeLock(q);
 }
 
-bool Locks::existEmptyLocks()
+bool Locks::existEmpty() const
 {
   for_( it, _pimpl->locks.begin(), _pimpl->locks.end() )
   {
@@ -212,8 +286,9 @@ public:
 
 };
 
-void Locks::removeEmptyLocks()
+void Locks::removeEmpty()
 {
+  MIL << "cleaning of locks" << endl;
   callback::SendReport<CleanEmptyLocksReport> report;
   report->start();
   size_t sum = _pimpl->locks.size();
@@ -223,6 +298,7 @@ void Locks::removeEmptyLocks()
 
   if( p.aborted() )
   {
+    MIL << "cleaning aborted" << endl;
     report->finish(CleanEmptyLocksReport::ABORTED);
   }
   else 
@@ -230,6 +306,9 @@ void Locks::removeEmptyLocks()
     report->finish(CleanEmptyLocksReport::NO_ERROR);
 
   }
+
+  if ( sum != _pimpl->locks.size() ) //some locks has been removed
+    _pimpl->locksDirty = true;
 }
 
 class LocksRemovePredicate
@@ -278,15 +357,17 @@ public:
     switch( contains(q,solvs) )
     {
     case 0:
-      return false;
+      return false; //another lock
     case 1:
       cs = SavingLocksReport::SAME_RESULTS;
       break;
     case 2:
       cs = SavingLocksReport::INTERSECT;
+      break;
     default:
       return true;
     }
+    MIL << "find conflict: " << cs << endl;
     switch (report->conflict(q,cs))
     {
     case SavingLocksReport::ABORT:
@@ -309,22 +390,36 @@ public:
 
 bool Locks::Impl::mergeList(callback::SendReport<SavingLocksReport>& report)
 {
+  MIL << "merging list old: " << locks.size()
+    << " to add: " << toAdd.size() << "to remove: " << toRemove.size() << endl;
   for_(it,toRemove.begin(),toRemove.end())
   {
-    if (!report->progress())
-      return false;
     std::set<sat::Solvable> s(it->begin(),it->end());
     locks.remove_if(LocksRemovePredicate(s,*it, report));
   }
 
   if (!report->progress())
     return false;
-  locks.insert(locks.end(),toAdd.begin(),toAdd.end());
+
+  for_( it, toAdd.begin(), toAdd.end() )
+  {
+    if( std::find( locks.begin(), locks.end(), *it ) == locks.end() )
+      locks.push_back( *it );
+  }
+
+  toAdd.clear();
+  toRemove.clear();
+
   return true;
 }
 
-void Locks::saveLocks( const Pathname& file )
+void Locks::merge()
 {
+  if( (_pimpl->toAdd.size() | _pimpl->toRemove.size())==0)
+  {
+    return; //nothing to merge
+  }
+
   callback::SendReport<SavingLocksReport> report;
   report->start();
   if (!_pimpl->mergeList(report))
@@ -332,10 +427,48 @@ void Locks::saveLocks( const Pathname& file )
     report->finish(SavingLocksReport::ABORTED);
     return;
   }
+  DBG << "locks merged" << endl;
+  report->finish(SavingLocksReport::NO_ERROR);
+  _pimpl->locksDirty = true;
+}
+
+void Locks::save( const Pathname& file )
+{
+  if( ((_pimpl->toAdd.size() | _pimpl->toRemove.size())==0)
+      && !_pimpl->locksDirty )
+  {
+    DBG << "nothing changed in locks - no write to file" << endl;
+    return;
+  }
+
+  callback::SendReport<SavingLocksReport> report;
+  report->start();
+
+  if ((_pimpl->toAdd.size() | _pimpl->toRemove.size())!=0)
+  {
+    if (!_pimpl->mergeList(report))
+    {
+      report->finish(SavingLocksReport::ABORTED);
+      return;
+    }
+  }
+
   DBG << "writed "<< _pimpl->locks.size() << "locks" << endl;
   writePoolQueriesToFile( file, _pimpl->locks.begin(), _pimpl->locks.end() );
   report->finish(SavingLocksReport::NO_ERROR);
 }
 
-} // ns locks
+void Locks::removeDuplicates()
+{
+  size_type sum = size();
+  for_(it,_pimpl->locks.begin(),_pimpl->locks.end())
+  {
+    if ( find(_pimpl->locks.begin(),it,*it) != it )
+      _pimpl->locks.erase(it--); //-- to avoid using break iterator
+  }
+  
+  if (sum!=size())
+    _pimpl->locksDirty = true;
+}
+
 } // ns zypp