#
SET(LIBZYPP_MAJOR "16")
SET(LIBZYPP_COMPATMINOR "0")
-SET(LIBZYPP_MINOR "5")
-SET(LIBZYPP_PATCH "2")
+SET(LIBZYPP_MINOR "6")
+SET(LIBZYPP_PATCH "0")
#
-# LAST RELEASED: 16.5.2 (0)
+# LAST RELEASED: 16.6.0 (0)
# (The number in parenthesis is LIBZYPP_COMPATMINOR)
#=======
-------------------------------------------------------------------
+Mon Mar 27 17:10:52 CEST 2017 - ma@suse.de
+
+- Fix invalidation of PoolItems if Pool IDs are reused (bsc#1028661)
+- version 16.6.0 (0)
+
+-------------------------------------------------------------------
Mon Mar 27 09:33:26 CEST 2017 - ma@suse.de
- Fix X-libcurl-Empty-Header-Workaround (bsc#1030919)
--- /dev/null
+<channel><subchannel>
+<package>
+ <name>package</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</package>
+<patch>
+ <name>patch</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</patch>
+<pattern>
+ <name>pattern</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</pattern>
+<product>
+ <name>product</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</product>
+<srcpackage>
+ <name>srcpackage</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</srcpackage>
+<application>
+ <name>application</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</application>
+</subchannel></channel>
--- /dev/null
+<?xml version="1.0"?>
+<test>
+<setup arch="x86_64">
+ <channel file="repo.xml" name="SEQA" priority="99" />
+</setup>
+</test>
--- /dev/null
+<channel><subchannel>
+<application>
+ <name>application</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</application>
+<package>
+ <name>package</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</package>
+<patch>
+ <name>patch</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</patch>
+<pattern>
+ <name>pattern</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</pattern>
+<product>
+ <name>product</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</product>
+<srcpackage>
+ <name>srcpackage</name>
+ <vendor>unkown</vendor>
+ <history><update>
+ <arch>x86_64</arch>
+ <version>4</version>
+ <release>1</release>
+ </update></history>
+</srcpackage>
+</subchannel></channel>
--- /dev/null
+<?xml version="1.0"?>
+<test>
+<setup arch="x86_64">
+ <channel file="oper.xml" name="SeqB" priority="99" />
+</setup>
+</test>
Digest
Deltarpm
Edition
+ ExtendedPool
Fetcher
FileChecker
Flags
--- /dev/null
+#include <boost/test/auto_unit_test.hpp>
+
+#include <iostream>
+
+#include "TestSetup.h"
+#include <zypp/base/LogTools.h>
+
+#include <zypp/ResObjects.h>
+#include <zypp/ResPool.h>
+
+using boost::unit_test::test_case;
+using std::cin;
+using std::cout;
+using std::cerr;
+using std::endl;
+using namespace zypp;
+
+static TestSetup test;
+
+void testcase_init()
+{
+// cout << "+++[repoinit]=======================" << endl;
+ test.loadTestcaseRepos( TESTS_SRC_DIR"/data/PoolReuseIds/SeqA" );
+// for ( auto && pi : ResPool::instance() )
+// cout << pi << " " << pi.resolvable() << endl;
+// cout << "---[repoinit]=======================" << endl;
+}
+
+void testcase_init2()
+{
+// cout << "+++[repoinit2]=======================" << endl;
+ sat::Pool::instance().reposEraseAll();
+ test.loadTestcaseRepos( TESTS_SRC_DIR"/data/PoolReuseIds/SeqB" );
+// for ( auto && pi : ResPool::instance() )
+// cout << pi << " " << pi.resolvable() << endl;
+// cout << "---[repoinit2]=======================" << endl;
+}
+
+void checkpi( const PoolItem & pi )
+{
+ BOOST_CHECK( pi.resolvable() );
+ BOOST_CHECK_EQUAL( pi.id(), pi.resolvable()->id() );
+ BOOST_CHECK_EQUAL( bool(asKind<Package>( pi.resolvable() )), isKind<Package>(pi) );
+ BOOST_CHECK_EQUAL( bool(asKind<Patch>( pi.resolvable() )), isKind<Patch>(pi) );
+ BOOST_CHECK_EQUAL( bool(asKind<Pattern>( pi.resolvable() )), isKind<Pattern>(pi) );
+ BOOST_CHECK_EQUAL( bool(asKind<Product>( pi.resolvable() )), isKind<Product>(pi) );
+ BOOST_CHECK_EQUAL( bool(asKind<SrcPackage>( pi.resolvable() )), isKind<SrcPackage>(pi) );
+ BOOST_CHECK_EQUAL( bool(asKind<Application>( pi.resolvable() )), isKind<Application>(pi) );
+}
+
+void repocheck()
+{
+// cout << "+++[repocheck]======================" << endl;
+ for ( auto && pi : ResPool::instance() )
+ {
+// cout << "??? " << pi << endl;
+ checkpi( pi );
+ }
+// cout << "---[repocheck]======================" << endl;
+}
+
+///////////////////////////////////////////////////////////////////
+// Check that after ERASING ALL REPOS and loading a new one, ResPool
+// actually creates new PoolItems rather than reusing already existing
+// ones.
+//
+// Adding/removing repos will not reuse poolIDs unless actually all
+// repos are removed from the pool. In this case ResPool must invalidate
+// ALL existing PoolItems (especially the Resolvable Pointers inside).
+//
+// SeqA SeqB
+// (1)package - (1)application
+// (2)pattern - (2)package
+// ... ...
+//
+// The two test repos have Resolvables of different kind in different
+// order. If ResPool fails to recreate the PoolItem, we'll experience
+// cast errors. PoolItem(1) will claim to be an application, but the
+// Resolvable is still the original one created for a package...
+///////////////////////////////////////////////////////////////////
+
+BOOST_AUTO_TEST_CASE(t_1) { testcase_init(); }
+BOOST_AUTO_TEST_CASE(t_2) { repocheck(); }
+BOOST_AUTO_TEST_CASE(t_4) { testcase_init2(); }
+BOOST_AUTO_TEST_CASE(t_5) { repocheck(); }
{
sat::Pool pool( satpool() );
bool addedItems = false;
+ bool reusedIDs = _watcherIDs.remember( pool.serialIDs() );
std::list<PoolItem> addedProducts;
_store.resize( pool.capacity() );
// the PoolItem got invalidated (e.g unloaded repo)
pi = PoolItem();
}
- else if ( s && ! pi )
+ else if ( reusedIDs || (s && ! pi) )
{
// new PoolItem to add
pi = PoolItem::makePoolItem( s ); // the only way to create a new one!
private:
/** Watch sat pools serial number. */
SerialNumberWatcher _watcher;
+ /** Watch sat pools Serial number of IDs - changes whenever resusePoolIDs==true - ResPool must also invalidate it's PoolItems! */
+ SerialNumberWatcher _watcherIDs;
mutable ContainerT _store;
mutable DefaultIntegral<bool,true> _storeDirty;
mutable Id2ItemT _id2item;
const SerialNumber & Pool::serial() const
{ return myPool().serial(); }
+ const SerialNumber & Pool::serialIDs() const
+ { return myPool().serialIDs(); }
+
void Pool::prepare() const
{ return myPool().prepare(); }
/** Housekeeping data serial number. */
const SerialNumber & serial() const;
+ /** Serial number changing whenever resusePoolIDs==true was used. ResPool must also invalidate it's PoolItems! */
+ const SerialNumber & serialIDs() const;
+
/** Update housekeeping data if necessary (e.g. whatprovides). */
void prepare() const;
// If the last repo is removed clear the pool to actually reuse all IDs.
// NOTE: the explicit ::repo_free above asserts all solvables are memset(0)!
if ( !_pool->urepos )
+ {
+ _serialIDs.setDirty(); // Indicate resusePoolIDs - ResPool must also invalidate it's PoolItems
::pool_freeallrepos( _pool, /*resusePoolIDs*/true );
+ }
}
int PoolImpl::_addSolv( CRepo * repo_r, FILE * file_r )
const SerialNumber & serial() const
{ return _serial; }
+ /** Serial number changing whenever resusePoolIDs==true was used. ResPool must also invalidate it's PoolItems! */
+ const SerialNumber & serialIDs() const
+ { return _serialIDs; }
+
/** Update housekeeping data (e.g. whatprovides).
* \todo actually requires a watcher.
*/
private:
/** sat-pool. */
CPool * _pool;
- /** Serial number. */
+ /** Serial number - changes with each Pool content change. */
SerialNumber _serial;
+ /** Serial number of IDs - changes whenever resusePoolIDs==true - ResPool must also invalidate it's PoolItems! */
+ SerialNumber _serialIDs;
/** Watch serial number. */
SerialNumberWatcher _watcher;
/** Additional \ref RepoInfo. */