From 8a3a911f8fb40ddcf70d58cbfe7b55ebdf028a04 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 11 Apr 2008 14:35:37 +0000 Subject: [PATCH] implement unlock --- zypp/Locks.cc | 156 ++++++++++++++++++++++++++++++++++++++++++++++++--- zypp/ZYppCallbacks.h | 36 ++++++++++++ 2 files changed, 183 insertions(+), 9 deletions(-) diff --git a/zypp/Locks.cc b/zypp/Locks.cc index 913ceb7..ecc3e77 100644 --- a/zypp/Locks.cc +++ b/zypp/Locks.cc @@ -46,15 +46,15 @@ class Locks::Impl { public: std::list locks; + std::list toAdd; + std::list toRemove; + + bool mergeList(callback::SendReport& report); + }; Locks::Locks() : _pimpl(new Impl){} -void Locks::saveLocks( const Pathname& file ) -{ - writePoolQueriesToFile( file, _pimpl->locks.begin(), _pimpl->locks.end() ); -} - /** * iterator that takes lock, lock all solvables from query * and send query to output iterator @@ -96,7 +96,16 @@ void Locks::addLock( const PoolQuery& query ) PoolItem item(*it); item.status().setLock(true,ResStatus::USER); } - _pimpl->locks.push_back( query ); + std::list::iterator i = find(_pimpl->toRemove.begin(), + _pimpl->toRemove.end(), query); + if ( i != _pimpl->toRemove.end() ) + { + _pimpl->toRemove.erase(i); + } + else + { + _pimpl->toAdd.push_back( query ); + } } void Locks::addLock(const ui::Selectable& selectable) @@ -110,6 +119,37 @@ void Locks::addLock(const ui::Selectable& selectable) addLock( q ); } +void Locks::unlock( const PoolQuery& query ) +{ + for_( it,query.begin(),query.end() ) + { + PoolItem item(*it); + item.status().setLock(false,ResStatus::USER); + } + + std::list::iterator i = find(_pimpl->toAdd.begin(), + _pimpl->toAdd.end(), query); + if ( i != _pimpl->toAdd.end() ) + { + _pimpl->toAdd.erase(i); + } + else + { + _pimpl->toRemove.push_back( query ); + } +} + +void Locks::unlock( const ui::Selectable& s ) +{ + PoolQuery q; + q.addAttribute( sat::SolvAttr::name,s.name() ); + q.addKind( s.kind() ); + q.setMatchExact(); + q.setCaseSensitive(true); + q.requireAll(); + unlock(q); +} + bool Locks::existEmptyLocks() { for_( it, _pimpl->locks.begin(), _pimpl->locks.end() ) @@ -122,7 +162,7 @@ bool Locks::existEmptyLocks() } //handle locks during removing -class LocksRemovePredicate{ +class LocksCleanPredicate{ private: bool skip_rest; size_t searched; @@ -130,7 +170,7 @@ private: callback::SendReport &report; public: - LocksRemovePredicate(size_t count, callback::SendReport &_report): skip_rest(false),searched(0),all(count), report(_report){} + LocksCleanPredicate(size_t count, callback::SendReport &_report): skip_rest(false),searched(0),all(count), report(_report){} bool aborted(){ return skip_rest; } @@ -173,7 +213,7 @@ void Locks::removeEmptyLocks() callback::SendReport report; report->start(); size_t sum = _pimpl->locks.size(); - LocksRemovePredicate p(sum, report); + LocksCleanPredicate p(sum, report); _pimpl->locks.remove_if(p); @@ -188,5 +228,103 @@ void Locks::removeEmptyLocks() } } +class LocksRemovePredicate +{ +private: + std::set& solvs; + const PoolQuery& query; + callback::SendReport& report; + bool aborted_; + + //1 for subset of set, 2 only intersect, 0 for not intersect + int contains(const PoolQuery& q, std::set& s) + { + bool intersect = false; + for_( it,q.begin(),q.end() ) + { + if ( s.find(*it)!=s.end() ) + { + intersect = true; + } + else + { + if (intersect) + return 2; + } + } + return intersect ? 1 : 0; + } + +public: + LocksRemovePredicate(std::set& s, const PoolQuery& q, + callback::SendReport& r) + : solvs(s), query(q),report(r),aborted_(false) {} + + bool operator()(const PoolQuery& q) + { + if (aborted()) + return false; + if( q==query ) //identical + return true; + + SavingLocksReport::ConflictState cs; + switch( contains(q,solvs) ) + { + case 0: + return false; + case 1: + cs = SavingLocksReport::SAME_RESULTS; + break; + case 2: + cs = SavingLocksReport::INTERSECT; + default: + return true; + } + switch (report->conflict(q,cs)) + { + case SavingLocksReport::ABORT: + aborted_ = true; + return false; + case SavingLocksReport::DELETE: + return true; + case SavingLocksReport::IGNORE: + return false; + } + WAR << "should not reached, some state is missing" << endl; + return false; + } + + bool aborted(){ return aborted_; } +}; + +bool Locks::Impl::mergeList(callback::SendReport& report) +{ + for_(it,toRemove.begin(),toRemove.end()) + { + if (!report->progress()) + return false; + std::set 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()); + return true; +} + +void Locks::saveLocks( const Pathname& file ) +{ + callback::SendReport report; + report->start(); + if (!_pimpl->mergeList(report)) + { + report->finish(SavingLocksReport::ABORTED); + return; + } + writePoolQueriesToFile( file, _pimpl->locks.begin(), _pimpl->locks.end() ); + report->finish(SavingLocksReport::NO_ERROR); +} + } // ns locks } // ns zypp diff --git a/zypp/ZYppCallbacks.h b/zypp/ZYppCallbacks.h index 2904ba3..208a89c 100644 --- a/zypp/ZYppCallbacks.h +++ b/zypp/ZYppCallbacks.h @@ -658,6 +658,42 @@ class PoolQuery; }; + struct SavingLocksReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + DELETE, // delete conflicted lock + IGNORE // skip conflict lock + }; + + enum Error { + NO_ERROR, + ABORTED // cleaning aborted + }; + + enum ConflictState{ + SAME_RESULTS, + INTERSECT + }; + + virtual void start() {} + + virtual bool progress() /*still alive*/ + { return true; } + + /** + * When user unlock something which is locked by non-identical query + */ + virtual Action conflict( + const PoolQuery&, /*problematic query*/ + ConflictState + ) { return DELETE; } + + virtual void finish( + Error /*error*/ + ) {} + + }; ///////////////////////////////////////////////////////////////// } // namespace locks /////////////////////////////////////////////////////////////////// -- 2.7.4