Author: dmacvicar Date: Wed Jun 6 16:44:54 2007 New Revision: 5692 URL: http://svn.opensuse.org/viewcvs/zypp?rev=5692&view=rev Log: zypper port starts. zypp2 to zypp Added: trunk/libzypp/zypp/cache/ trunk/libzypp/zypp/cache/CacheException.cc trunk/libzypp/zypp/cache/CacheException.h trunk/libzypp/zypp/cache/CacheFSCK.cc trunk/libzypp/zypp/cache/CacheFSCK.h trunk/libzypp/zypp/cache/CacheInitializer.cpp trunk/libzypp/zypp/cache/CacheInitializer.h trunk/libzypp/zypp/cache/CacheStore.cpp trunk/libzypp/zypp/cache/CacheStore.h trunk/libzypp/zypp/cache/CacheTypes.cc trunk/libzypp/zypp/cache/CacheTypes.h trunk/libzypp/zypp/cache/DESIGN-WRITE-API.txt trunk/libzypp/zypp/cache/ResolvableQuery.cc trunk/libzypp/zypp/cache/ResolvableQuery.h trunk/libzypp/zypp/cache/SQLITE3X-README.txt trunk/libzypp/zypp/cache/Utils.cpp trunk/libzypp/zypp/cache/Utils.h trunk/libzypp/zypp/cache/schema/ trunk/libzypp/zypp/cache/schema/DESIGN-SCHEMA.txt trunk/libzypp/zypp/cache/schema/mkarray.c trunk/libzypp/zypp/cache/schema/schema.sql trunk/libzypp/zypp/cache/sqlite3x/ trunk/libzypp/zypp/cache/sqlite3x/sqlite3x.hpp trunk/libzypp/zypp/cache/sqlite3x/sqlite3x_command.cpp trunk/libzypp/zypp/cache/sqlite3x/sqlite3x_connection.cpp trunk/libzypp/zypp/cache/sqlite3x/sqlite3x_exception.cpp trunk/libzypp/zypp/cache/sqlite3x/sqlite3x_reader.cpp trunk/libzypp/zypp/cache/sqlite3x/sqlite3x_transaction.cpp trunk/libzypp/zypp/cache/sqliteext/ trunk/libzypp/zypp/cache/sqliteext/zlibext.c Modified: trunk/libzypp/zypp/CMakeLists.txt Modified: trunk/libzypp/zypp/CMakeLists.txt URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/CMakeLists.txt?rev=5... ============================================================================== --- trunk/libzypp/zypp/CMakeLists.txt (original) +++ trunk/libzypp/zypp/CMakeLists.txt Wed Jun 6 16:44:54 2007 @@ -3,6 +3,11 @@ #################################################################### ADD_DEFINITIONS(-DLOCALEDIR=\"/usr/share/libzypp\" -DTEXTDOMAIN=\"zypp\" ) +ADD_EXECUTABLE(mkarray ${CMAKE_SOURCE_DIR}/zypp/cache/schema/mkarray.c ) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) +#FILE(WRITE filename "message to write"... ) + +ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_BINARY_DIR}/zypp/sqlite-schema.h PRE_BUILD COMMAND "${CMAKE_BINARY_DIR}/zypp/mkarray" ARGS "${CMAKE_SOURCE_DIR}/zypp/cache/schema/schema.sql" "schemaData" "${CMAKE_BINARY_DIR}/zypp/sqlite-schema.h" DEPENDS mkarray DEPENDS ${CMAKE_SOURCE_DIR}/zypp/cache/schema/schema.sql ) SET( zypp_SRCS ZConfig.cc @@ -81,6 +86,11 @@ OnMediaLocation.cc Fetcher.cc FileChecker.cc + Repository.cc + RepoInfo.cc + RepoStatus.cc + RepoManager.cc + RepositoryFactory.cc ) SET( zypp_HEADERS @@ -178,6 +188,11 @@ ZYppCommitResult.h ZYppFactory.h FileChecker.h + Repository.h + RepoInfo.h + RepoStatus.h + RepoManager.h + RepositoryFactory.h ) INSTALL( FILES ${zypp_HEADERS} DESTINATION "${CMAKE_INSTALL_PREFIX}/include/zypp" ) @@ -415,6 +430,7 @@ parser/LibXMLHelper.cc parser/SAXParser.cc parser/XMLNodeIterator.cc + parser/RepoFileReader.cc ) SET( zypp_parser_HEADERS @@ -427,6 +443,7 @@ parser/SAXParser.h parser/XMLNodeIterator.h parser/xml_parser_assert.h + parser/RepoFileReader.h ) INSTALL( FILES @@ -440,6 +457,7 @@ parser/susetags/PackagesFileReader.cc parser/susetags/PackagesLangFileReader.cc parser/susetags/PatternFileReader.cc + parser/susetags/RepoParser.cc ) SET( zypp_parser_susetags_HEADERS @@ -450,6 +468,7 @@ parser/susetags/PackagesFileReader.h parser/susetags/PackagesLangFileReader.h parser/susetags/PatternFileReader.h + parser/susetags/RepoParser.h ) INSTALL( FILES @@ -998,9 +1017,92 @@ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/zypp/zypp_detail ) +SET( zypp_cache_SRCS + ${CMAKE_BINARY_DIR}/zypp/sqlite-schema.h + cache/CacheInitializer.cpp + cache/CacheException.cc + cache/CacheTypes.cc + cache/ResolvableQuery.cc + cache/CacheStore.cpp + cache/CacheFSCK.cc + cache/Utils.cpp +) + +SET( zypp_cache_HEADERS + cache/CacheTypes.h + cache/CacheInitializer.h + cache/CacheException.h + cache/CacheStore.h + cache/CacheFSCK.h + cache/ResolvableQuery.h + cache/Utils.h +) + +#INSTALL( FILES +# ${zypp_cache_HEADERS} +# DESTINATION ${CMAKE_INSTALL_PREFIX}/include/zypp/cache +#) + +SET( zypp_cache_sqlite3x_SRCS + cache/sqlite3x/sqlite3x_command.cpp + cache/sqlite3x/sqlite3x_connection.cpp + cache/sqlite3x/sqlite3x_exception.cpp + cache/sqlite3x/sqlite3x_reader.cpp + cache/sqlite3x/sqlite3x_transaction.cpp +) + +SET( zypp_cache_sqlite3x_HEADERS + cache/sqlite3x/sqlite3x.hpp +) + +#INSTALL( FILES +# ${zypp_cache_sqlite3x_HEADERS} +# DESTINATION ${CMAKE_INSTALL_PREFIX}/include/zypp/cache/sqlite3x +#) + +SET( zypp_repository_SRCS + repo/dummy.cc + repo/RepositoryImpl.cc + repo/RepoException.cc + repo/RepoType.cc +) + +SET( zypp_repository_HEADERS + repo/dummy.h + repo/RepositoryImpl.h + repo/RepoException.h + repo/RepoType.h +) + +SET( zypp_repository_cached_SRCS + repo/cached/RepoImpl.cc + repo/cached/PackageImpl.cc +) + +SET( zypp_repository_cached_HEADERS + repo/cached/RepoImpl.h + repo/cached/PackageImpl.h +) + +SET( zypp_repository_data_SRCS + repo/memory/PackageImpl.cc + repo/memory/PatternImpl.cc + repo/memory/ProductImpl.cc + repo/memory/SrcPackageImpl.cc +) + +SET( zypp_repository_data_HEADERS + repo/memory/PackageImpl.h + repo/memory/PatternImpl.h + repo/memory/ProductImpl.h + repo/memory/SrcPackageImpl.h +) + SET( zypp_lib_SRCS ${zypp_detail_SRCS} ${zypp_capability_SRCS} +${zypp_cache_SRCS} +${zypp_cache_sqlite3x_SRCS} ${zypp_pool_SRCS} ${zypp_parser_tagfile_SRCS} ${zypp_parser_susetags_SRCS} @@ -1017,6 +1119,9 @@ ${zypp_media_proxyinfo_SRCS} ${zypp_media_SRCS} ${zypp_url_SRCS} +${zypp_repository_SRCS} +${zypp_repository_cached_SRCS} +${zypp_repository_data_SRCS} ${zypp_target_store_xml_SRCS} ${zypp_target_store_SRCS} ${zypp_target_rpm_SRCS} @@ -1039,6 +1144,8 @@ ${zypp_target_rpm_HEADERS} ${zypp_parser_yum2_HEADERS} ${zypp_capability_HEADERS} +${zypp_cache_HEADERS} +${zypp_cache_sqlite3x_HEADERS} ${zypp_ui_HEADERS} ${zypp_parser_xmlstore_HEADERS} ${zypp_data_HEADERS} @@ -1056,6 +1163,7 @@ ${zypp_HEADERS} ${zypp_zypp_detail_HEADERS} ${zypp_thread_HEADERS} +${zypp_repository_HEADERS} ${zypp_source_susetags_HEADERS} ${zypp_target_modalias_HEADERS} ${zypp_target_HEADERS} @@ -1112,6 +1220,7 @@ ADD_LIBRARY(zypp SHARED ${zypp_lib_SRCS}) SET_TARGET_PROPERTIES( zypp PROPERTIES VERSION "${LIBZYPP_VERSION_INFO}" ) +ADD_DEPENDENCIES(zypp schema_header) # System libraries TARGET_LINK_LIBRARIES(zypp boost_filesystem boost_regex util ) TARGET_LINK_LIBRARIES(zypp ${DBUS_LIBRARY} ) Added: trunk/libzypp/zypp/cache/CacheException.cc URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheException... ============================================================================== --- trunk/libzypp/zypp/cache/CacheException.cc (added) +++ trunk/libzypp/zypp/cache/CacheException.cc Wed Jun 6 16:44:54 2007 @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ +/** \file zypp/repo/CacheException.cc + * +*/ +#include <iostream> +//#include "zypp/base/Logger.h" +#include "zypp/cache/CacheException.h" + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CacheException::CacheException + // METHOD TYPE : Ctor + // + CacheException::CacheException() + : Exception( "Cache exception" ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CacheException::CacheException + // METHOD TYPE : Ctor + // + CacheException::CacheException( const std::string & msg_r ) + : Exception( msg_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CacheException::~CacheException + // METHOD TYPE : Dtor + // + CacheException::~CacheException() throw() + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CacheException::dumpOn + // METHOD TYPE : std::ostream & + // + std::ostream & CacheException::dumpOn( std::ostream & str ) const + { + return Exception::dumpOn( str ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// Added: trunk/libzypp/zypp/cache/CacheException.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheException... ============================================================================== --- trunk/libzypp/zypp/cache/CacheException.h (added) +++ trunk/libzypp/zypp/cache/CacheException.h Wed Jun 6 16:44:54 2007 @@ -0,0 +1,57 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ + +#ifndef ZYPP_REPO_REPOEXCEPTION_H +#define ZYPP_REPO_REPOEXCEPTION_H + +#include <iosfwd> +#include <string> + +#include "zypp/base/Exception.h" +#include "zypp/base/UserRequestException.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /** + * \short Exception for cache errors + */ + class CacheException : public Exception + { + public: + /** Default ctor */ + CacheException(); + /** Ctor */ + CacheException( const std::string & msg_r ); + /** Dtor */ + virtual ~CacheException() throw(); + protected: + virtual std::ostream & dumpOn( std::ostream & str ) const; + }; + /////////////////////////////////////////////////////////////////// + + /** + * The record you supplied can't be found + */ + class CacheRecordNotFoundException : public CacheException + { + + }; + + ///////////////////////////////////////////////////////////////// + } // namespace cache + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_TAGFILE_PARSEEXCEPTION_H Added: trunk/libzypp/zypp/cache/CacheFSCK.cc URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheFSCK.cc?r... ============================================================================== --- trunk/libzypp/zypp/cache/CacheFSCK.cc (added) +++ trunk/libzypp/zypp/cache/CacheFSCK.cc Wed Jun 6 16:44:54 2007 @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ +/** \file zypp/cache/CacheFSCK.cc + * +*/ +#include <iostream> +#include "zypp/base/Logger.h" +#include "zypp/base/Exception.h" +#include "zypp/cache/CacheFSCK.h" +#include "zypp/cache/sqlite3x/sqlite3x.hpp" + +using namespace zypp; +using namespace zypp::cache; +using namespace std; +using namespace sqlite3x; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CacheFSCK::Impl + // + /** CacheFSCK implementation. */ + struct CacheFSCK::Impl + { + + public: + + Impl( const Pathname &dbdir ) + : _dbdir(dbdir) + { + + } + + void start() + { + try + { + sqlite3_connection con((_dbdir + "zypp.db").asString().c_str()); + //con.executenonquery("BEGIN;"); + + sqlite3_command cmd( con, "PRAGMA integrity_check;"); + sqlite3_reader reader = cmd.executereader(); + while(reader.read()) + { + cout << reader.getstring(0) << endl; + } + } + catch( const std::exception &e ) + { + ZYPP_RETHROW(Exception(e.what())); + } + } + + private: + friend Impl * rwcowClone<Impl>( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + + Pathname _dbdir; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CacheFSCK::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const CacheFSCK::Impl & obj ) + { + return str << "CacheFSCK::Impl"; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CacheFSCK + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CacheFSCK::CacheFSCK + // METHOD TYPE : Ctor + // + CacheFSCK::CacheFSCK( const Pathname &dbdir ) + : _pimpl( new Impl(dbdir) ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CacheFSCK::~CacheFSCK + // METHOD TYPE : Dtor + // + CacheFSCK::~CacheFSCK() + {} + + void CacheFSCK::start() + { + _pimpl->start(); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const CacheFSCK & obj ) + { + return str << *obj._pimpl; + } + + ///////////////////////////////////////////////////////////////// + } // namespace cache + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// Added: trunk/libzypp/zypp/cache/CacheFSCK.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheFSCK.h?re... ============================================================================== --- trunk/libzypp/zypp/cache/CacheFSCK.h (added) +++ trunk/libzypp/zypp/cache/CacheFSCK.h Wed Jun 6 16:44:54 2007 @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ +/** \file zypp/cache/CacheFSCK.h + * +*/ +#ifndef ZYPP2_CACHE_CACHEFSCK_H +#define ZYPP2_CACHE_CACHEFSCK_H + +#include <iosfwd> + +#include "zypp/base/PtrTypes.h" +#include "zypp/Pathname.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CacheFSCK + // + /** + * Check for consistency of the cache + **/ + class CacheFSCK + { + friend std::ostream & operator<<( std::ostream & str, const CacheFSCK & obj ); + + public: + /** Implementation */ + class Impl; + + public: + /** + * Default ctor + * + * \param dbdir Cache directory + */ + CacheFSCK( const Pathname &dbdir ); + + void start(); + /** Dtor */ + ~CacheFSCK(); + + public: + + private: + /** Pointer to implementation */ + RWCOW_pointer<Impl> _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CacheFSCK Stream output */ + std::ostream & operator<<( std::ostream & str, const CacheFSCK & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace cache + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_CACHE_CACHEFSCK_H Added: trunk/libzypp/zypp/cache/CacheInitializer.cpp URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheInitializ... ============================================================================== --- trunk/libzypp/zypp/cache/CacheInitializer.cpp (added) +++ trunk/libzypp/zypp/cache/CacheInitializer.cpp Wed Jun 6 16:44:54 2007 @@ -0,0 +1,115 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ + +#include <vector> +#include <sstream> +#include <fstream> + +#include "zypp/base/Logger.h" +#include "zypp/base/String.h" +#include "zypp/base/Measure.h" +#include "zypp/cache/CacheInitializer.h" +#include "zypp/target/store/PersistentStorage.h" +#include "zypp/cache/Utils.h" + +#include "sqlite-schema.h" + +#define ZYPP_DB_FILE "/var/lib/zypp/zypp.db" + +using namespace sqlite3x; +using namespace std; +using zypp::debug::Measure; + +////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +namespace cache +{ ///////////////////////////////////////////////////////////////// + +struct CacheInitializer::Impl +{ + Impl( const Pathname &root_r ) + : root(root_r), just_initialized(false) + { + } + //typedef std::map<media::MediaNr, media::MediaAccessId> MediaMap + shared_ptrsqlite3x::sqlite3_connection con; + Pathname root; + bool just_initialized; +}; + +CacheInitializer::CacheInitializer( const Pathname &root_r, const Pathname &db_file ) + : _pimpl( new Impl( root_r ) ) +{ + try + { + _pimpl->con.reset( new sqlite3_connection( ( _pimpl->root + db_file).asString().c_str()) ); + + if( ! tablesCreated() ) + { + createTables(); + _pimpl->just_initialized = true; + _pimpl->con->close(); + MIL << "Source cache initialized" << std::endl; + } + else + { + MIL << "Source cache already initialized" << std::endl; + } + } + catch( const exception &ex ) + { + ZYPP_RETHROW(Exception(ex.what())); + //ERR << "Exception Occured: " << ex.what() << endl; + } + +} + +bool CacheInitializer::justInitialized() const +{ + return _pimpl->just_initialized; +} + +CacheInitializer::~CacheInitializer() +{ + +} + +bool CacheInitializer::tablesCreated() const +{ + Measure timer("Check tables exist"); + unsigned int count = _pimpl->con->executeint("select count(*) from sqlite_master where type='table';"); + timer.elapsed(); + return ( count > 0 ); +} + +void CacheInitializer::createTables() +{ + Measure timer("Create database tables"); + MIL << "Initializing cache schema..." << endl; + sqlite3_transaction trans(*_pimpl->con); + { + string sql( schemaData, _schemaData_size); + //ERR << "Executing " << statements[i] << endl; + MIL << "Schema size: " << sql.size() << endl; + _pimpl->con->execute(sql.c_str()); + } + trans.commit(); + timer.elapsed(); +} + +std::ostream & CacheInitializer::dumpOn( std::ostream & str ) const +{ + return str; +} + +} +} + Added: trunk/libzypp/zypp/cache/CacheInitializer.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheInitializ... ============================================================================== --- trunk/libzypp/zypp/cache/CacheInitializer.h (added) +++ trunk/libzypp/zypp/cache/CacheInitializer.h Wed Jun 6 16:44:54 2007 @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ + +#ifndef ZYPP_CacheInitializer_H +#define ZYPP_CacheInitializer_H + +#include <iosfwd> +#include <string> + +#include "zypp/base/PtrTypes.h" +#include "zypp/base/ReferenceCounted.h" +#include "zypp/base/NonCopyable.h" +#include "zypp/Pathname.h" +#include "zypp/cache/sqlite3x/sqlite3x.hpp" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CacheInitializer + // + class CacheInitializer + { + friend std::ostream & operator<<( std::ostream & str, const CacheInitializer & obj ); + + public: + /** + * Tries to initialize the source cache if it was not + * \throws Exception When cant initialize + */ + CacheInitializer( const Pathname &root_r, const Pathname &db_file ); + virtual ~CacheInitializer(); + + /** + * only true when cache was not initialized before + * and was just initialized with success + */ + bool justInitialized() const; + protected: + bool tablesCreated() const; + void createTables(); + /** Overload to realize stream output. */ + virtual std::ostream & dumpOn( std::ostream & str ) const; + private: + /** Implementation. */ + class Impl; + /** Pointer to implementation. */ + RW_pointer<Impl> _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CacheInitializer Stream output */ + inline std::ostream & operator<<( std::ostream & str, const CacheInitializer & obj ) + { return obj.dumpOn( str ); } + + + ///////////////////////////////////////////////////////////////// + } // namespace cache + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SOURCE_CacheInitializer_H Added: trunk/libzypp/zypp/cache/CacheStore.cpp URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheStore.cpp... ============================================================================== --- trunk/libzypp/zypp/cache/CacheStore.cpp (added) +++ trunk/libzypp/zypp/cache/CacheStore.cpp Wed Jun 6 16:44:54 2007 @@ -0,0 +1,1036 @@ + +#include <sqlite3.h> +#include <map> +#include "zypp/cache/sqlite3x/sqlite3x.hpp" + +#include "zypp/base/Logger.h" +#include "zypp/base/Measure.h" +#include "zypp/ZYppFactory.h" +#include "zypp/ZYpp.h" +#include "zypp/ZConfig.h" + +#include "zypp/cache/CacheInitializer.h" +#include "zypp/cache/CacheStore.h" +#include "zypp/cache/CacheException.h" + +using namespace std; +using namespace zypp; +using namespace zypp::capability; +using namespace zypp::cache; +using zypp::data::RecordId; +using namespace sqlite3x; + +using zypp::debug::Measure; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +namespace cache +{ ///////////////////////////////////////////////////////////////// + +typedef shared_ptr<sqlite3_command> sqlite3_command_ptr; + +struct CacheStore::Impl +{ + Impl( const Pathname &dbdir ) + : name_cache_hits(0) + { + cache::CacheInitializer initializer(dbdir, "zypp.db"); + if ( initializer.justInitialized() ) + { + MIL << "database " << (dbdir + "zypp.db") << " was just created" << endl; + } + + try + { + con.open( (dbdir + "zypp.db").asString().c_str()); + //_insert_resolvable_cmd = new sqlite3_command( *_con, INSERT_RESOLVABLE_QUERY ); + //_insert_package_cmd = new sqlite3_command( *_con, INSERT_PACKAGE_QUERY ); + } + catch(exception &ex) + { + //ZYPP_CAUGHT(ex); + ZYPP_THROW(Exception(ex.what())); + } + + + // initialize all pre-compiled statements + + insert_resolvable_in_repository_cmd.reset( new sqlite3_command( con, "insert into resolvables_repositories (resolvable_id, repository_id) values (:resolvable_id, :repository_id);" )); + + update_repository_cmd.reset( new sqlite3_command( con, "update repositories set checksum=:checksum, timestamp=:timestamp where id=:repository_id;" )); + + select_repository_cmd.reset( new sqlite3_command( con, "select id from repositories where alias=:alias;" )); + insert_repository_cmd.reset( new sqlite3_command( con, "insert into repositories (alias,timestamp) values (:alias, :timestamp);" )); + + select_name_cmd.reset( new sqlite3_command( con, "select id from names where name=:name;" )); + insert_name_cmd.reset( new sqlite3_command( con, "insert into names (name) values (:name);" )); + + select_dirname_cmd.reset( new sqlite3_command( con, "select id from dir_names where name=:name;" )); + insert_dirname_cmd.reset( new sqlite3_command( con, "insert into dir_names (name) values (:name);" )); + + select_filename_cmd.reset( new sqlite3_command( con, "select id from file_names where name=:name;" )); + insert_filename_cmd.reset( new sqlite3_command( con, "insert into file_names (name) values (:name);" )); + + select_file_cmd.reset( new sqlite3_command( con, "select id from files where dir_name_id=:dir_name_id and file_name_id=:file_name_id;" )); + insert_file_cmd.reset( new sqlite3_command( con, "insert into files (dir_name_id,file_name_id) values (:dir_name_id,:file_name_id);" )); + + select_type_cmd.reset( new sqlite3_command( con, "select id from types where class=:class and name=:name;" )); + insert_type_cmd.reset( new sqlite3_command( con, "insert into types (class,name) values (:class,:name);" )); + + set_shared_flag_cmd.reset( new sqlite3_command( con, "update resolvables set shared_id=:shared_id where id=:resolvable_id;" )); + + append_text_attribute_cmd.reset( new sqlite3_command( con, "insert into text_attributes ( weak_resolvable_id, lang_id, attr_id, text ) values ( :rid, :lang_id, :attr_id, :text );" )); + append_num_attribute_cmd.reset( new sqlite3_command( con, "insert into numeric_attributes ( weak_resolvable_id, attr_id, value ) values ( :rid, :attr_id, :value );" )); + + //insert_dependency_entry_cmd.reset( new sqlite3_command( con, "insert into capabilities ( resolvable_id, dependency_type, refers_kind ) values ( :resolvable_id, :dependency_type, :refers_kind );" )); + append_file_dependency_cmd.reset( new sqlite3_command( con, "insert into file_capabilities ( resolvable_id, dependency_type, refers_kind, file_id ) values ( :resolvable_id, :dependency_type, :refers_kind, :file_id );" )); + append_named_dependency_cmd.reset( new sqlite3_command( con, "insert into named_capabilities ( resolvable_id, dependency_type, refers_kind, name_id, version, release, epoch, relation ) values ( :resolvable_id, :dependency_type, :refers_kind, :name_id, :version, :release, :epoch, :relation );" )); + + append_modalias_dependency_cmd.reset( new sqlite3_command( con, "insert into modalias_capabilities ( resolvable_id, dependency_type, refers_kind, name, value, relation ) values ( :resolvable_id, :dependency_type, :refers_kind, :name, :value, :relation );" )); + + append_hal_dependency_cmd.reset( new sqlite3_command( con, "insert into hal_capabilities ( resolvable_id, dependency_type, refers_kind, name, value, relation ) values ( :resolvable_id, :dependency_type, :refers_kind, :name, :value, :relation );" )); + + append_other_dependency_cmd.reset( new sqlite3_command( con, "insert into other_capabilities ( resolvable_id, dependency_type, refers_kind, value ) values ( :resolvable_id, :dependency_type, :refers_kind, :value );" )); + + append_resolvable_cmd.reset( new sqlite3_command( con, "insert into resolvables ( name, version, release, epoch, arch, kind, repository_id ) values ( :name, :version, :release, :epoch, :arch, :kind, :repository_id );" )); + + count_shared_cmd.reset( new sqlite3_command( con, "select count(id) from resolvables where shared_id=:rid;" )); + + insert_patchrpm_cmd.reset( new sqlite3_command (con, + "insert into patch_packages (media_nr, location, checksum, download_size, build_time) " + "values (:media_nr, :location, :checksum, :download_size, :build_time);" )); + insert_deltarpm_cmd.reset( new sqlite3_command (con, + "insert into delta_packages (media_nr, location, checksum, download_size, build_time, " + "baseversion_version, baseversion_release, baseversion_epoch, baseversion_checksum, " + "baseversion_build_time, baseversion_sequence_info) " + "values (:media_nr, :location, :checksum, :download_size, :build_time, " + ":baseversion_version, :baseversion_release, :baseversion_epoch, :baseversion_checksum, " + ":baseversion_build_time, :baseversion_sequence_info);" )); + append_patch_baseversion_cmd.reset( new sqlite3_command (con, + "insert into patch_packages_baseversions (patch_package_id, version, release, epoch) " + "values (:patch_package_id, :version, :release, :epoch)" )); + + + // disable autocommit + con.executenonquery("BEGIN;"); + } + + Impl() + { + Impl( getZYpp()->homePath() ); + } + + ~Impl() + { + MIL << "name cache hits: " << name_cache_hits << " | cache size: " << name_cache.size() << endl; + } + + /** + * SQL statements + * (we precompile them + */ + sqlite3_connection con; + + sqlite3_command_ptr update_repository_cmd; + sqlite3_command_ptr insert_resolvable_in_repository_cmd; + + sqlite3_command_ptr select_name_cmd; + sqlite3_command_ptr insert_name_cmd; + + sqlite3_command_ptr select_dirname_cmd; + sqlite3_command_ptr insert_dirname_cmd; + + sqlite3_command_ptr select_filename_cmd; + sqlite3_command_ptr insert_filename_cmd; + + sqlite3_command_ptr select_repository_cmd; + sqlite3_command_ptr insert_repository_cmd; + + sqlite3_command_ptr select_file_cmd; + sqlite3_command_ptr insert_file_cmd; + + sqlite3_command_ptr select_type_cmd; + sqlite3_command_ptr insert_type_cmd; + + //sqlite3_command_ptr insert_dependency_entry_cmd; + + sqlite3_command_ptr append_file_dependency_cmd; + sqlite3_command_ptr append_named_dependency_cmd; + sqlite3_command_ptr append_modalias_dependency_cmd; + sqlite3_command_ptr append_hal_dependency_cmd; + sqlite3_command_ptr append_other_dependency_cmd; + + sqlite3_command_ptr append_resolvable_cmd; + + sqlite3_command_ptr append_text_attribute_cmd; + sqlite3_command_ptr append_num_attribute_cmd; + + sqlite3_command_ptr set_shared_flag_cmd; + + sqlite3_command_ptr count_shared_cmd; + + sqlite3_command_ptr insert_patchrpm_cmd; + sqlite3_command_ptr insert_deltarpm_cmd; + sqlite3_command_ptr append_patch_baseversion_cmd; + + map<string, RecordId> name_cache; + map< pair<string,string>, RecordId> type_cache; + int name_cache_hits; +}; + + +CacheStore::CacheStore( const Pathname &dbdir ) + : _pimpl( new Impl(dbdir) ) +{ + +} + +CacheStore::CacheStore() + : _pimpl( new Impl() ) +{ + +} + +CacheStore::~CacheStore() +{ + +} + +void CacheStore::commit() +{ + _pimpl->con.executenonquery("COMMIT;"); +} + +void CacheStore::appendResObjectAttributes( const data::RecordId &rid, + const data::ResObject_Ptr & res ) +{ + appendTranslatedStringAttribute( rid, "ResObject", "description", res->description ); + appendTranslatedStringAttribute( rid, "ResObject", "summary", res->summary ); + appendNumericAttribute( rid, "ResObject", "installedSize", res->installedSize ); + appendNumericAttribute( rid, "ResObject", "buildTime", res->buildTime ); + appendBooleanAttribute( rid, "ResObject", "installOnly", res->installOnly ); + appendStringAttribute( rid, "ResObject", "vendor", res->vendor ); + appendTranslatedStringAttribute( rid, "ResObject", "licenseToConfirm", res->licenseToConfirm ); + appendTranslatedStringAttribute( rid, "ResObject", "insnotify", res->insnotify ); + appendTranslatedStringAttribute( rid, "ResObject", "delnotify", res->delnotify ); +} + + +void CacheStore::appendPackageBaseAttributes( const RecordId & pkgid, + const data::Packagebase_Ptr & package ) +{ + appendStringAttribute( pkgid, "Package", "checksum", package->repositoryLocation.fileChecksum.checksum() ); + appendStringAttribute( pkgid, "Package", "checksumType", package->repositoryLocation.fileChecksum.type() ); + appendStringAttribute( pkgid, "Package", "buildhost", package->buildhost ); + appendStringAttribute( pkgid, "Package", "distribution", package->distribution ); + appendStringAttribute( pkgid, "Package", "license", package->license ); + appendStringAttribute( pkgid, "Package", "group", package->packager ); + appendStringAttribute( pkgid, "Package", "url", package->url ); + appendStringAttribute( pkgid, "Package", "operatingSystem", package->operatingSystem ); + appendStringAttribute( pkgid, "Package", "prein", package->prein ); + appendStringAttribute( pkgid, "Package", "postin", package->postin ); + appendStringAttribute( pkgid, "Package", "preun", package->preun ); + appendStringAttribute( pkgid, "Package", "postun", package->postun ); + appendStringContainerAttribute( pkgid, "Package", "keywords", package->keywords ); + appendStringContainerAttribute( pkgid, "Package", "authors", package->authors ); + appendStringAttribute( pkgid, "Package", "location", package->repositoryLocation.filePath.asString() ); +} + +void CacheStore::consumePackage( const RecordId & repository_id, + const data::Package_Ptr & package ) +{ + RecordId pkgid = appendResolvable( repository_id, ResTraits<Package>::kind, + NVRA( package->name, package->edition, package->arch ), package->deps ); + appendResObjectAttributes( pkgid, package ); + appendPackageBaseAttributes( pkgid, package ); +} + +void CacheStore::consumeSourcePackage( const data::RecordId & repository_id, + const data::SrcPackage_Ptr & package ) +{ + RecordId pkgid = appendResolvable( repository_id, ResTraits<SrcPackage>::kind, + NVRA( package->name, package->edition, package->arch ), package->deps ); + appendResObjectAttributes( pkgid, package ); + appendPackageBaseAttributes( pkgid, package ); +#warning TBD +} + +void CacheStore::consumePatch( const data::RecordId & repository_id, + const data::Patch_Ptr & patch) +{ + RecordId id = appendResolvable( + repository_id, ResTraits<Patch>::kind, + NVRA( patch->name, patch->edition, patch->arch ), patch->deps ); + + appendResObjectAttributes( id, patch ); + + // patch attributes + appendNumericAttribute( id, "Patch", "timestamp", patch->timestamp ); + appendStringAttribute( id, "Patch", "category", patch->category ); + appendBooleanAttribute( id, "Patch", "rebootNeeded", patch->rebootNeeded ); + appendBooleanAttribute( id, "Patch", "affectsPkgManager", patch->affectsPkgManager ); + + + DBG << "got patch " << patch->name << ", atoms: "; + // cosume atoms + for (setdata::ResObject_Ptr::const_iterator p = patch->atoms.begin(); + p != patch->atoms.end(); ++p) + { + data::PackageAtom_Ptr atom = dynamic_pointer_castdata::PackageAtom(*p); + if (atom) + { + DBG << atom->name << "(atom) "; + consumePackageAtom(repository_id, atom); + continue; + } + + data::Script_Ptr script = dynamic_pointer_castdata::Script(*p); + if (script) + { + DBG << script->name << "(script) "; + consumeScript(repository_id, script); + continue; + } + + data::Message_Ptr message = dynamic_pointer_castdata::Message(*p); + if (message) + { + DBG << message->name << "(message) "; + consumeMessage(repository_id, message); + continue; + } + + ERR << " ignoring !badatom! "; + if (*p) ERR << (*p)->name; + ERR << endl; + } + + DBG << endl; +} + +void CacheStore::consumePackageAtom( const data::RecordId & repository_id, + const data::PackageAtom_Ptr & atom ) +{ + RecordId id = appendResolvable( repository_id, ResTraits<Atom>::kind, + NVRA( atom->name, atom->edition, atom->arch ), atom->deps ); + appendResObjectAttributes( id, atom ); + appendPackageBaseAttributes( id, atom ); + + for (setdata::PatchRpm_Ptr::const_iterator p = atom->patchRpms.begin(); + p != atom->patchRpms.end(); ++p) + appendPatchRpm(*p); + + for (setdata::DeltaRpm_Ptr::const_iterator d = atom->deltaRpms.begin(); + d != atom->deltaRpms.end(); ++d) + appendDeltaRpm(*d); +} + +void CacheStore::consumeMessage( const data::RecordId & repository_id, + const data::Message_Ptr & message ) +{ + RecordId id = appendResolvable( repository_id, ResTraits<Message>::kind, + NVRA( message->name, message->edition, message->arch ), message->deps ); + appendResObjectAttributes( id, message ); + + appendTranslatedStringAttribute( id, "Message", "text", message->text ); +} + +void CacheStore::consumeScript( const data::RecordId & repository_id, + const data::Script_Ptr & script ) +{ + RecordId id = appendResolvable( repository_id, ResTraits<Script>::kind, + NVRA( script->name, script->edition, script->arch ), script->deps ); + appendResObjectAttributes( id, script ); + + appendStringAttribute( id, "Script", "doScript", script->doScript ); + appendStringAttribute( id, "Script", "doScriptLocation", script->doScriptLocation.filePath.asString() ); + appendStringAttribute( id, "Script", "doScriptChecksum", script->doScriptLocation.fileChecksum.checksum() ); + appendStringAttribute( id, "Script", "doScriptChecksumType", script->doScriptLocation.fileChecksum.type() ); + appendStringAttribute( id, "Script", "undoScript", script->undoScript ); + appendStringAttribute( id, "Script", "undoScriptLocation", script->undoScriptLocation.filePath.asString() ); + appendStringAttribute( id, "Script", "undoScriptChecksum", script->undoScriptLocation.fileChecksum.checksum() ); + appendStringAttribute( id, "Script", "undoScriptChecksumType", script->undoScriptLocation.fileChecksum.type() ); +} + +void CacheStore::consumePattern( const data::RecordId & repository_id, + const data::Pattern_Ptr & pattern ) +{ + RecordId id = appendResolvable( repository_id, ResTraits<Pattern>::kind, + NVRA( pattern->name, pattern->edition, pattern->arch ), pattern->deps ); + appendResObjectAttributes( id, pattern ); + + appendBooleanAttribute( id, "Pattern", "isDefault", pattern->isDefault ); + appendBooleanAttribute( id, "Pattern", "userVisible", pattern->userVisible ); + appendTranslatedStringAttribute( id, "Pattern", "category", pattern->category ); + appendStringAttribute( id, "Pattern", "icon", pattern->icon ); + appendStringAttribute( id, "Pattern", "order", pattern->order ); +} + +void CacheStore::consumeProduct( const data::RecordId & repository_id, + const data::Product_Ptr & product ) +{ + RecordId id = appendResolvable( repository_id, ResTraits<Product>::kind, + NVRA( product->name, product->edition, product->arch ), product->deps ); + appendResObjectAttributes( id, product ); + + appendTranslatedStringAttribute( id, "Product", "shortName", product->shortName ); + appendTranslatedStringAttribute( id, "Product", "longName", product->longName ); + appendStringContainerAttribute( id, "Product", "flags", product->flags ); + appendStringAttribute( id, "Pattern", "releasenotesUrl", product->releasenotesUrl.asString() ); + //! \todo figure out how to store list of Urls. A separate method appendUrlContainerAttribute? Or change it to plain string in ResolvableData.h? +// appendStringContainerAttribute( id, "Product", "updateUrls", product->updateUrls ); +// appendStringContainerAttribute( id, "Product", "extraUrls", product->extraUrls ); +// appendStringContainerAttribute( id, "Product", "optionalUrls", product->optionalUrls ); + appendStringAttribute( id, "Pattern", "distributionName", product->distributionName ); + appendStringAttribute( id, "Pattern", "distributionEdition", product->distributionEdition.asString() ); +} + +void CacheStore::consumeChangelog( const data::RecordId & repository_id, + const data::Resolvable_Ptr & resolvable, + const Changelog & changelog ) +{ + //! \todo maybe appendChangelog(const data::RecordId & resolvable_id, Changelog changelog) will be needed + //! for inserting the changelog using in-memory record id of corresponding resolvable. + //! (first, we'll see how fast is the inserting without remembering those ids) +} + +void CacheStore::consumeFilelist( const data::RecordId & repository_id, + const data::Resolvable_Ptr & resolvable, + const data::Filenames & filenames ) +{ + //! \todo maybe consumeFilelist(const data::RecordId & resolvable_id, data::Filenames &) will be needed +} + +RecordId CacheStore::appendResolvable( const RecordId &repository_id, + const Resolvable::Kind &kind, + const NVRA &nvra, + const data::Dependencies &deps ) +{ + _pimpl->append_resolvable_cmd->bind( ":name", nvra.name ); + _pimpl->append_resolvable_cmd->bind( ":version", nvra.edition.version() ); + _pimpl->append_resolvable_cmd->bind( ":release", nvra.edition.release() ); + _pimpl->append_resolvable_cmd->bind( ":epoch", static_cast<int>( nvra.edition.epoch() ) ); + _pimpl->append_resolvable_cmd->bind( ":arch", lookupOrAppendType("arch", nvra.arch.asString()) ); + _pimpl->append_resolvable_cmd->bind( ":kind", lookupOrAppendType("kind", kind.asString()) ); + _pimpl->append_resolvable_cmd->bind( ":repository_id", repository_id ); + + _pimpl->append_resolvable_cmd->executenonquery(); + + long long id = _pimpl->con.insertid(); + + appendDependencies( id, deps ); + /* + _pimpl->insert_resolvable_in_repository_cmd->bind(":repository_id", repository_id); + _pimpl->insert_resolvable_in_repository_cmd->bind(":resolvable_id", id); + _pimpl->insert_resolvable_in_repository_cmd->executenonquery();*/ + + return static_cast<RecordId>(id); + return 1; +} + +void CacheStore::appendDependencies( const RecordId &resolvable_id, const data::Dependencies &deps ) +{ + for ( data::Dependencies::const_iterator it = deps.begin(); it != deps.end(); ++it ) + { + appendDependencyList( resolvable_id, it->first, it->second ); + } +} + +void CacheStore::appendDependencyList( const RecordId &resolvable_id, zypp::Dep deptype, const data::DependencyList &caps ) +{ + for ( data::DependencyList::const_iterator it = caps.begin(); it != caps.end(); ++it ) + { + appendDependency( resolvable_id, deptype, *it ); + } +} + +void CacheStore::appendDependency( const RecordId &resolvable_id, zypp::Dep deptype, capability::CapabilityImpl::Ptr cap ) +{ + if ( cap == 0 ) + { + DBG << "invalid capability" << endl; + return; + } + + if ( capability::isKind<NamedCap>(cap) ) + { + appendNamedDependency( resolvable_id, deptype, capability::asKind<NamedCap>(cap) ); + } + else if ( capability::isKind<FileCap>(cap) ) + { + appendFileDependency( resolvable_id, deptype, capability::asKind<FileCap>(cap) ); + return; + } + else if ( capability::isKind<ModaliasCap>(cap) ) + { + appendModaliasDependency( resolvable_id, deptype, capability::asKind<ModaliasCap>(cap) ); + } + else if ( capability::isKind<HalCap>(cap) ) + { + appendHalDependency( resolvable_id, deptype, capability::asKind<HalCap>(cap) ); + } + else + { + appendUnknownDependency( resolvable_id, deptype, cap ); + } +} + +// RecordId CacheStore::lookupOrAppendNamedDependencyEntry( const RecordId name_id, const Edition &edition, const zypp::Rel &rel ) +// { +// _pimpl->select_named_dependency_cmd->bind( ":name_id", name_id); +// _pimpl->select_named_dependency_cmd->bind( ":version", edition.version() ); +// _pimpl->select_named_dependency_cmd->bind( ":release", edition.release() ); +// _pimpl->select_named_dependency_cmd->bind( ":epoch", static_cast<int>( edition.epoch() ) ); +// _pimpl->select_named_dependency_cmd->bind( ":relation", zypp_rel2db_rel( rel ) ); +// long long id = 0; +// try { +// id = _pimpl->select_named_dependency_cmd->executeint64(); +// } +// catch ( const sqlite3x::database_error &e ) +// { +// // does not exist +// _pimpl->append_named_dependency_entry_cmd->bind( ":name_id", name_id); +// _pimpl->append_named_dependency_entry_cmd->bind( ":version", edition.version() ); +// _pimpl->append_named_dependency_entry_cmd->bind( ":release", edition.release() ); +// _pimpl->append_named_dependency_entry_cmd->bind( ":epoch", static_cast<int>( edition.epoch() ) ); +// _pimpl->append_named_dependency_entry_cmd->bind( ":relation", zypp_rel2db_rel( rel ) ); +// _pimpl->append_named_dependency_entry_cmd->executenonquery(); +// id = _pimpl->con.insertid(); +// return static_cast<RecordId>(id); +// } +// return static_cast<RecordId>(id); +// } + +void CacheStore::appendNamedDependency( const RecordId &resolvable_id, zypp::Dep deptype, capability::NamedCap::Ptr cap ) +{ + if ( !cap ) + ZYPP_THROW(Exception("bad versioned dep")); + //DBG << "versioned : " << cap << endl; + + //RecordId capability_id = appendDependencyEntry( resolvable_id, deptype, cap->refers() ); + RecordId name_id = lookupOrAppendName(cap->name()); + + _pimpl->append_named_dependency_cmd->bind( ":resolvable_id", resolvable_id ); + _pimpl->append_named_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) ); + _pimpl->append_named_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) ); + + //_pimpl->append_named_dependency_cmd->bind( ":capability_id", capability_id); + _pimpl->append_named_dependency_cmd->bind( ":name_id", name_id); + _pimpl->append_named_dependency_cmd->bind( ":version", cap->edition().version() ); + _pimpl->append_named_dependency_cmd->bind( ":release", cap->edition().release() ); + _pimpl->append_named_dependency_cmd->bind( ":epoch", static_cast<int>( cap->edition().epoch() ) ); + _pimpl->append_named_dependency_cmd->bind( ":relation", lookupOrAppendType("rel", cap->op().asString()) ); + _pimpl->append_named_dependency_cmd->executenonquery(); + + //delete cmd; +} + +void CacheStore::appendModaliasDependency( const RecordId &resolvable_id, + zypp::Dep deptype, + capability::ModaliasCap::Ptr cap ) +{ + if ( !cap ) + ZYPP_THROW(Exception("Null modalias capability")); + + _pimpl->append_modalias_dependency_cmd->bind( ":resolvable_id", resolvable_id ); + _pimpl->append_modalias_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) ); + _pimpl->append_modalias_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) ); + + //_pimpl->append_modalias_dependency_cmd->bind( ":capability_id", capability_id); + _pimpl->append_modalias_dependency_cmd->bind( ":name", cap->name()); + _pimpl->append_modalias_dependency_cmd->bind( ":value", cap->value()); + _pimpl->append_modalias_dependency_cmd->bind( ":relation", lookupOrAppendType("rel", cap->op().asString()) ); + + _pimpl->append_modalias_dependency_cmd->executenonquery(); + //delete cmd; +} + +void CacheStore::appendHalDependency( const RecordId &resolvable_id, + zypp::Dep deptype, + capability::HalCap::Ptr cap ) +{ + if ( !cap ) + ZYPP_THROW(Exception("Null HAL capability")); + + _pimpl->append_hal_dependency_cmd->bind( ":resolvable_id", resolvable_id ); + _pimpl->append_hal_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) ); + _pimpl->append_hal_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) ); + + //_pimpl->append_hal_dependency_cmd->bind( ":capability_id", capability_id); + _pimpl->append_hal_dependency_cmd->bind( ":name", cap->name()); + _pimpl->append_hal_dependency_cmd->bind( ":value", cap->value()); + _pimpl->append_hal_dependency_cmd->bind( ":relation", lookupOrAppendType("rel", cap->op().asString()) ); + + _pimpl->append_hal_dependency_cmd->executenonquery(); + //delete cmd; +} + +void CacheStore::appendFileDependency( const RecordId &resolvable_id, zypp::Dep deptype, + capability::FileCap::Ptr cap ) +{ + if ( !cap ) + ZYPP_THROW(Exception("Null file capability")); + + //RecordId capability_id = appendDependencyEntry( resolvable_id, deptype, cap->refers() ); + RecordId file_id = lookupOrAppendFile(cap->filename()); + + _pimpl->append_file_dependency_cmd->bind( ":resolvable_id", resolvable_id ); + _pimpl->append_file_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) ); + _pimpl->append_file_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) ); + + //_pimpl->append_file_dependency_cmd->bind( ":capability_id", capability_id); + _pimpl->append_file_dependency_cmd->bind( ":file_id", file_id); + + _pimpl->append_file_dependency_cmd->executenonquery(); + //delete cmd; +} + +void CacheStore::appendUnknownDependency( const RecordId &resolvable_id, + zypp::Dep deptype, + capability::CapabilityImpl::Ptr cap ) +{ + if ( !cap ) + ZYPP_THROW(Exception("Null unknown capability")); + + _pimpl->append_other_dependency_cmd->bind( ":resolvable_id", resolvable_id ); + _pimpl->append_other_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) ); + _pimpl->append_other_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) ); + _pimpl->append_other_dependency_cmd->bind( ":value", cap->encode()); + + _pimpl->append_hal_dependency_cmd->executenonquery(); + //delete cmd; +} + + +/** \todo lookupOrAppend ? */ +RecordId CacheStore::appendPatchRpm(const data::PatchRpm_Ptr & prpm) +{ + RecordId id; + + //! \todo what's this? _pimpl->insert_patchrpm_cmd->bind(":media_nr", ???); + _pimpl->insert_patchrpm_cmd->bind(":location", prpm->location.filePath.asString()); + _pimpl->insert_patchrpm_cmd->bind(":checksum", prpm->location.fileChecksum.checksum()); + //! \todo checksum type + _pimpl->insert_patchrpm_cmd->bind(":download_size", static_castByteCount::SizeType(prpm->location.fileSize)); + _pimpl->insert_patchrpm_cmd->bind(":build_time", prpm->buildTime.asSeconds()); + _pimpl->insert_patchrpm_cmd->executenonquery(); + + id = _pimpl->con.insertid(); + + for (setdata::BaseVersion_Ptr::const_iterator bv = prpm->baseVersions.begin(); + bv != prpm->baseVersions.end(); ++bv) + { + _pimpl->append_patch_baseversion_cmd->bind(":patch_package_id", id); + _pimpl->append_patch_baseversion_cmd->bind(":version", (*bv)->edition.version()); + _pimpl->append_patch_baseversion_cmd->bind(":release", (*bv)->edition.release()); + _pimpl->append_patch_baseversion_cmd->bind(":epoch", (int) (*bv)->edition.epoch()); + _pimpl->append_patch_baseversion_cmd->executenonquery(); + } + + return id; +} + + +/** \todo lookupOrAppend ? */ +RecordId CacheStore::appendDeltaRpm(const data::DeltaRpm_Ptr & drpm) +{ + RecordId id; + + //! \todo what's this? _pimpl->insert_deltarpm_cmd->bind(":media_nr", ???); + _pimpl->insert_deltarpm_cmd->bind(":location", drpm->location.filePath.asString()); + _pimpl->insert_deltarpm_cmd->bind(":checksum", drpm->location.fileChecksum.checksum()); + //! \todo checksum type + _pimpl->insert_deltarpm_cmd->bind(":download_size", static_castByteCount::SizeType(drpm->location.fileSize)); + _pimpl->insert_deltarpm_cmd->bind(":build_time", drpm->buildTime.asSeconds()); + + _pimpl->insert_deltarpm_cmd->bind(":baseversion_version", drpm->baseVersion.edition.version()); + _pimpl->insert_deltarpm_cmd->bind(":baseversion_release", drpm->baseVersion.edition.release()); + _pimpl->insert_deltarpm_cmd->bind(":baseversion_epoch", (int) drpm->baseVersion.edition.epoch()); + _pimpl->insert_deltarpm_cmd->bind(":baseversion_build_time", drpm->baseVersion.buildTime.asSeconds()); + _pimpl->insert_deltarpm_cmd->bind(":baseversion_checksum", drpm->baseVersion.checkSum.checksum()); + _pimpl->insert_deltarpm_cmd->bind(":baseversion_sequence_info", drpm->baseVersion.sequenceInfo); + + _pimpl->insert_deltarpm_cmd->executenonquery(); + id = _pimpl->con.insertid(); + + return id; +} + + +// RecordId CacheStore::appendDependencyEntry( const RecordId &resolvable_id, zypp::Dep deptype, const Resolvable::Kind &refers ) +// { +// //DBG << "rid: " << resolvable_id << " deptype: " << deptype << " " << "refers: " << refers << endl; +// _pimpl->insert_dependency_entry_cmd->bind( ":resolvable_id", resolvable_id ); +// +// db::DependencyType dt = zypp_deptype2db_deptype(deptype); +// if ( dt == db::DEP_TYPE_UNKNOWN ) +// { +// ZYPP_THROW(Exception("Unknown depenency type")); +// } +// +// _pimpl->insert_dependency_entry_cmd->bind( ":dependency_type", zypp_deptype2db_deptype(deptype) ); +// _pimpl->insert_dependency_entry_cmd->bind( ":refers_kind", zypp_kind2db_kind(refers) ); +// +// _pimpl->insert_dependency_entry_cmd->executenonquery(); +// //delete cmd; +// long long id = _pimpl->con.insertid(); +// return static_cast<RecordId>(id); +// } + +RecordId CacheStore::lookupOrAppendFile( const Pathname &path ) +{ + RecordId dir_name_id = lookupOrAppendDirName(path.dirname().asString()); + RecordId file_name_id = lookupOrAppendFileName(path.basename()); + + _pimpl->select_file_cmd->bind(":dir_name_id", dir_name_id); + _pimpl->select_file_cmd->bind(":file_name_id", file_name_id); + long long id = 0; + try { + id = _pimpl->select_file_cmd->executeint64(); + } + catch ( const sqlite3x::database_error &e ) + { + // does not exist + _pimpl->insert_file_cmd->bind(":dir_name_id", dir_name_id); + _pimpl->insert_file_cmd->bind(":file_name_id", file_name_id); + _pimpl->insert_file_cmd->executenonquery(); + id = _pimpl->con.insertid(); + return static_cast<RecordId>(id); + + } + return static_cast<RecordId>(id); +} + +void CacheStore::updateRepository( const RecordId &id, + const string &checksum, + const Date ×tamp ) +{ + _pimpl->update_repository_cmd->bind(":repository_id", id); + _pimpl->update_repository_cmd->bind(":checksum", checksum); + _pimpl->update_repository_cmd->bind(":timestamp", static_cast<int>((Date::ValueType) timestamp) ); + _pimpl->insert_repository_cmd->executenonquery(); +} + +RecordId CacheStore::lookupOrAppendRepository( const string &alias ) +{ + _pimpl->select_repository_cmd->bind(":alias", alias); + + long long id = 0; + try { + id = _pimpl->select_repository_cmd->executeint64(); + } + catch ( const sqlite3x::database_error &e ) + { + // does not exist + _pimpl->insert_repository_cmd->bind(":alias", alias); + _pimpl->insert_repository_cmd->bind(":timestamp", static_cast<int>((Date::ValueType) Date::now()) ); + _pimpl->insert_repository_cmd->executenonquery(); + id = _pimpl->con.insertid(); + return static_cast<RecordId>(id); + + } + return static_cast<RecordId>(id); +} + +void CacheStore::cleanRepository( const data::RecordId &id ) +{ + sqlite3_command cmd( _pimpl->con, "delete from repositories where id=:id"); + cmd.bind(":id", id); + + try + { + cmd.executenonquery(); + } + catch ( const sqlite3x::database_error &e ) + { + ZYPP_THROW(CacheRecordNotFoundException()); + } +} + +void CacheStore::cleanRepository( const std::string &alias ) +{ + cleanRepository(lookupRepository(alias)); +} + +RepoStatus CacheStore::repositoryStatus( const data::RecordId &id ) +{ + sqlite3_command cmd( _pimpl->con, "select id,alias,checksum,timestamp from repositories where id=:id"); + cmd.bind(":id", id); + + try + { + sqlite3_reader reader = cmd.executereader(); + RepoStatus status; + while ( reader.read() ) + { + status.setChecksum( reader.getstring(2) ); + status.setTimestamp( reader.getstring(3) ); + } + return status; + } + catch ( const sqlite3x::database_error &e ) + { + ZYPP_THROW(CacheRecordNotFoundException()); + } +} + +RepoStatus CacheStore::repositoryStatus( const string &alias ) +{ + return repositoryStatus(lookupRepository(alias)); +} + +bool CacheStore::isCached( const string &alias ) +{ + try + { + lookupRepository(alias); + } + catch( const CacheRecordNotFoundException &e ) + { + return false; + } + + return true; +} + +RecordId CacheStore::lookupRepository( const string &alias ) +{ + sqlite3_command cmd(_pimpl->con, "select id from repositories where alias=:alias;"); + cmd.bind(":alias", alias); + + long long id = 0; + try { + id = cmd.executeint64(); + } + catch ( const sqlite3x::database_error &e ) + { + ZYPP_THROW(CacheRecordNotFoundException()); + } + return id; +} + +RecordId CacheStore::lookupOrAppendType( const string &klass, const string &name ) +{ + pair<string, string> thetype = make_pair(klass,name); + if ( _pimpl->type_cache.find(thetype) != _pimpl->type_cache.end() ) + { + //_pimpl->name_cache_hits++; + return _pimpl->type_cache[thetype]; + } + + _pimpl->select_type_cmd->bind(":class", klass); + _pimpl->select_type_cmd->bind(":name", name); + long long id = 0; + try { + id = _pimpl->select_type_cmd->executeint64(); + _pimpl->type_cache[thetype] = id; + } + catch ( const sqlite3x::database_error &e ) + { + // does not exist + _pimpl->insert_type_cmd->bind(":class", klass); + _pimpl->insert_type_cmd->bind(":name", name); + _pimpl->insert_type_cmd->executenonquery(); + id = _pimpl->con.insertid(); + return id; + } + return id; +} + +RecordId CacheStore::lookupOrAppendName( const string &name ) +{ + if ( _pimpl->name_cache.find(name) != _pimpl->name_cache.end() ) + { + _pimpl->name_cache_hits++; + return _pimpl->name_cache[name]; + } + + _pimpl->select_name_cmd->bind(":name", name); + long long id = 0; + try { + id = _pimpl->select_name_cmd->executeint64(); + _pimpl->name_cache[name] = id; + } + catch ( const sqlite3x::database_error &e ) + { + // does not exist + _pimpl->insert_name_cmd->bind(":name", name); + _pimpl->insert_name_cmd->executenonquery(); + id = _pimpl->con.insertid(); + return static_cast<RecordId>(id); + + } + return static_cast<RecordId>(id); +} + +RecordId CacheStore::lookupOrAppendDirName( const string &name ) +{ + _pimpl->select_dirname_cmd->bind(":name", name); + long long id = 0; + try { + id = _pimpl->select_dirname_cmd->executeint64(); + } + catch ( const sqlite3x::database_error &e ) + { + // does not exist + _pimpl->insert_dirname_cmd->bind(":name", name); + _pimpl->insert_dirname_cmd->executenonquery(); + id = _pimpl->con.insertid(); + return static_cast<RecordId>(id); + + } + return static_cast<RecordId>(id); +} + +RecordId CacheStore::lookupOrAppendFileName( const string &name ) +{ + _pimpl->select_filename_cmd->bind(":name", name); + long long id = 0; + try { + id = _pimpl->select_filename_cmd->executeint64(); + } + catch ( const sqlite3x::database_error &e ) + { + // does not exist + _pimpl->insert_filename_cmd->bind(":name", name); + _pimpl->insert_filename_cmd->executenonquery(); + id = _pimpl->con.insertid(); + return static_cast<RecordId>(id); + + } + return static_cast<RecordId>(id); +} + +void CacheStore::setSharedData( const data::RecordId &resolvable_id, + const data::RecordId &shared_id ) +{ + _pimpl->set_shared_flag_cmd->bind(":resolvable_id", resolvable_id); + + if ( shared_id == data::noRecordId ) + _pimpl->set_shared_flag_cmd->bind(":shared_id"); + else + _pimpl->set_shared_flag_cmd->bind(":shared_id", shared_id); + + _pimpl->set_shared_flag_cmd->executenonquery(); +} + +void CacheStore::appendBooleanAttribute( const data::RecordId & resolvable_id, + const std::string & klass, + const std::string & name, + bool value) +{ + RecordId type_id = lookupOrAppendType( klass, name ); + appendNumericAttribute( resolvable_id, type_id, value ? 1 : 0 ); +} + +void CacheStore::appendNumericAttribute( const data::RecordId &resolvable_id, + const std::string &klass, + const std::string &name, + int value ) +{ + RecordId type_id = lookupOrAppendType( klass, name ); + appendNumericAttribute( resolvable_id, type_id, value ); +} + +void CacheStore::appendNumericAttribute( const RecordId &resolvable_id, + const RecordId &type_id, + int value ) +{ + // weak resolvable_id + _pimpl->append_num_attribute_cmd->bind(":rid", resolvable_id ); + _pimpl->append_num_attribute_cmd->bind(":attr_id", type_id ); + + _pimpl->append_num_attribute_cmd->bind(":value", value ); + + _pimpl->append_num_attribute_cmd->executenonquery(); +} + + +void CacheStore::appendTranslatedStringAttribute( const data::RecordId &resolvable_id, + const std::string &klass, + const std::string &name, + const TranslatedText &text ) +{ + set<Locale> locales = text.locales(); + for ( set<Locale>::const_iterator it = locales.begin(); it != locales.end(); ++it ) + { + appendStringAttributeTranslation( resolvable_id, *it, klass, name, text.text(*it) ); + } +} + + +void CacheStore::appendStringAttributeTranslation( const data::RecordId &resolvable_id, + const Locale &locale, + const std::string &klass, + const std::string &name, + const std::string &text ) +{ + // don't bother with writing if the string is empty + if (text.empty()) return; + + RecordId lang_id = lookupOrAppendType("lang", + locale.code().empty() ? "none" : locale.code() ); + RecordId type_id = lookupOrAppendType( klass, name ); + appendStringAttribute( resolvable_id, lang_id, type_id, text ); +} + +void CacheStore::appendStringAttribute( const data::RecordId &resolvable_id, + const std::string &klass, + const std::string &name, + const std::string &value ) +{ + // don't bother with writing if the string is empty + if (value.empty()) return; + + RecordId type_id = lookupOrAppendType(klass, name); + appendStringAttribute( resolvable_id, type_id, value ); +} + +void CacheStore::appendStringAttribute( const RecordId &resolvable_id, + const RecordId &type_id, + const std::string &value ) +{ + // don't bother with writing if the string is empty + if (value.empty()) return; + + RecordId lang_id = lookupOrAppendType("lang", "none"); + appendStringAttribute( resolvable_id, lang_id, type_id, value ); +} + +void CacheStore::appendStringAttribute( const RecordId &resolvable_id, + const RecordId &lang_id, + const RecordId &type_id, + const string &value ) +{ + // don't bother with writing if the string is empty + if (value.empty()) return; + + // weak resolvable_id + _pimpl->append_text_attribute_cmd->bind(":rid", resolvable_id ); + _pimpl->append_text_attribute_cmd->bind(":lang_id", lang_id ); + _pimpl->append_text_attribute_cmd->bind(":attr_id", type_id ); + + _pimpl->append_text_attribute_cmd->bind(":text", value ); + + _pimpl->append_text_attribute_cmd->executenonquery(); +} + +template <class _Container> +void CacheStore::appendStringContainerAttribute( const data::RecordId &resolvable_id, + const std::string &klass, + const std::string &name, + const _Container &cont ) +{ + // don't bother with writing if the container is empty + if (cont.empty()) return; + + string value = str::join(cont, ZConfig().cacheDBSplitJoinSeparator()); + + appendStringAttribute( resolvable_id, klass, name, value ); +} + +} +} + Added: trunk/libzypp/zypp/cache/CacheStore.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheStore.h?r... ============================================================================== --- trunk/libzypp/zypp/cache/CacheStore.h (added) +++ trunk/libzypp/zypp/cache/CacheStore.h Wed Jun 6 16:44:54 2007 @@ -0,0 +1,675 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ + +#ifndef ZYPP_CacheStore_H +#define ZYPP_CacheStore_H + +#include <iosfwd> +#include <string> + +#include "zypp/base/ReferenceCounted.h" +#include "zypp/base/NonCopyable.h" +#include "zypp/base/PtrTypes.h" +#include "zypp/Pathname.h" +#include "zypp/NVRA.h" +#include "zypp/capability/CapabilityImpl.h" +#include "zypp/capability/Capabilities.h" + +#include "zypp/data/ResolvableDataConsumer.h" +#include "zypp/data/RecordId.h" + +#include "zypp/base/PtrTypes.h" +#include "zypp/RepoStatus.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /** + * The cache store caches resolvable data. + * + * \code + * CacheStore store("/path"); + * RecordId repository_id = + * store.lookupOrAppendRepository("some-alias"); + * store.consumePackage( repository_id, package_ptr ); + * store.commit(); + * \endcode + * + * \note Data will not be commited until you explicitely commit. + */ + class CacheStore : public data::ResolvableDataConsumer + { + public: + + CacheStore(); + virtual ~CacheStore(); + + /** + * Constructor for the CacheStore + * + * \note a transaction will be started from the moment the + * CacheStore is instanciated. + * + * The data will be saved in the directory specified in + * \a dbdir. \a dbdir must exist. + */ + CacheStore( const Pathname &dbdir ); + + /** + * Commit the changes. + */ + void commit(); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume a package, inserting it in the cache, under + * \param repository_id ownership. + * \param package Package data + */ + virtual void consumePackage(const data::RecordId &repository_id, + const data::Package_Ptr & package); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume a source package, inserting it in the cache, under + * \param catalog_id ownership. + * \param srcpackage Source package data + */ + virtual void consumeSourcePackage( + const data::RecordId &catalog_id, + const data::SrcPackage_Ptr & srcpackage ); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume a patch, inserting it in the cache, under + * \param repository_id ownership. + * \param patch Patch data + */ + virtual void consumePatch( const data::RecordId &repository_id, + const data::Patch_Ptr & patch ); + + /** + * Implementation of the \ref ResolvableConsumer interface. + * + * Consume a package atom, inserting it in the cache, under + * \a repository_id ownership. + * + * \param repository_id record id of repository to which to append the resolvable. + * \param atom package atom data + * + * \note this is somewhat specific to current YUM patch metadata design + * and may change (to consumeAtom(data::RecordId,data::Atom)). + */ + virtual void consumePackageAtom( const data::RecordId &repository_id, + const data::PackageAtom_Ptr & atom ); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume a message, inserting it in the cache, under + * \param repository_id ownership. + * \param message Message data + */ + virtual void consumeMessage( const data::RecordId & repository_id, + const data::Message_Ptr & message); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume a script, inserting it in the cache, under + * \param repository_id ownership. + * \param script Script data + */ + virtual void consumeScript( const data::RecordId & repository_id, + const data::Script_Ptr & script); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume a pattern, inserting it in the cache, under + * \param repository_id ownership. + * \param pattern Pattern data + */ + virtual void consumePattern( const data::RecordId & repository_id, + const data::Pattern_Ptr & pattern ); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume a product, inserting it in the cache, under + * \param repository_id ownership. + * \param pattern Pattern data + */ + virtual void consumeProduct( const data::RecordId &repository_id, + const data::Product_Ptr & product ); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume changelog of a resolvable, inserting it in the cache. + * \param repository_id ownership. + * \param resolvable resolvable for which the changelog data are to be saved + * \param changelog the changelog + * \todo see implementation + */ + virtual void consumeChangelog( const data::RecordId & repository_id, + const data::Resolvable_Ptr & resolvable, + const Changelog & changelog ); + + /** + * Implementation of the \ref ResolvableConsumer interface + * + * Consume filelist of a resolvable, inserting it in the cache. + * \param repository_id ownership. + * \param resolvable resolvable for which the filelist is to be saved + * \param filenames list of filenames the resolvable contains + * \todo see implementation + */ + virtual void consumeFilelist( const data::RecordId &repository_id, + const data::Resolvable_Ptr & resolvable, + const data::Filenames & filenames ); + + /** + * Appends a resolvable to the store. + * + * You have to specify with \a kind of resolvable are you inserting + * and its \c NVRA (name version release and architecture ). + * Optionaly you can pass a list of \c CapabilityImpl::Ptr + * as dependencies for the resolvable. + * + * You have to specify the RecordId for the repository owning + * this resolvable. Yuu can obtain it with + * \ref lookupOrAppendRepository + * + * You can create those \a deps using \ref capability::parse + * functions, or the build methods to create specific types + * of capabilities: + * \ref capability::buildVersioned for \c VersionedCap + * \ref capability::buildNamed for \c NamedCap + * etc. + * + * Once the resolvable is inserted, you will get back the id + * if it in the store. Which you can use for later adding + * other properties. + * + */ + data::RecordId appendResolvable( const data::RecordId &repository_id, + const Resolvable::Kind &kind, + const NVRA &nvra, + const data::Dependencies &deps ); + + /** + * Adds dependencies to the store + * + * A map of dependency lists has to be specified. The map contains + * list of capablities for each dependency type \ref zypp::Dep + * + * \a resolvable_id is the resolvable Id in the CacheStore + * that will own those capabilities. + * + * FIXME should it \throw if the resolvable does not exist? + */ + void appendDependencies( const data::RecordId &resolvable_id, + const data::Dependencies &dependencies ); + + /** + * Adds dependencies to the store + * + * A lists of dependencies \a dlist to be specified. Among + * which type of dependencies \ref zypp::Dep it is as + * the \a deptype argument. + * + * \a resolvable_id is the resolvable Id in the CacheStore + * that will own those capabilities. + * + * FIXME should it \throw if the resolvable does not exist? + */ + void appendDependencyList( const data::RecordId &resolvable_id, + zypp::Dep deptype, + const data::DependencyList &dlist ); + + /** + * Adds a dependency to the store. + * + * A \ref CapabilityImpl::Ptr argument \a cap has to be specified. + * Among which type of dependency \ref zypp::Dep it is as + * the \a deptype argument. + * + * \a resolvable_id is the resolvable Id in the CacheStore + * that will own the capability + * + * FIXME should it \throw if the resolvable does not exist? + */ + void appendDependency( const data::RecordId &resolvable_id, + zypp::Dep deptype, + capability::CapabilityImpl::Ptr cap ); + + /** + * Adds a Named dependency to the store. + * + * A \ref NamedCap::Ptr \a dlist to be specified. Among + * which type of dependency \ref zypp::Dep it is as + * the \a deptype argument. + * + * \a resolvable_id is the resolvable Id in the CacheStore + * that will own the capability + * + * You can create the named capability using either + * \ref capability::parse or \ref capability::buildNamed + * + * FIXME should it \throw if the resolvable does not exist? + */ + void appendNamedDependency( const data::RecordId &, zypp::Dep, + capability::NamedCap::Ptr); + + /** + * Adds a file dependency to the store. + * + * A \ref FileCap::Ptr \a dlist to be specified. Among + * which type of dependency \ref zypp::Dep it is as + * the \a deptype argument. + * + * \a resolvable_id is the resolvable Id in the CacheStore + * that will own the capability + * + * You can create the file capability using either + * \ref capability::parse or \ref capability::buildFile + * + * FIXME should it \throw if the resolvable does not exist? + */ + void appendFileDependency( const data::RecordId &, zypp::Dep, + capability::FileCap::Ptr); + + /** + * Adds a Modalias dependency to the store. + * + * A \ref ModaliasCap::Ptr \a cap to be specified. Among + * which type of dependency \ref zypp::Dep it is as + * the \a deptype argument. + * + * \a resolvable_id is the resolvable Id in the CacheStore + * that will own the capability + * + * You can create the modalias capability using either + * \ref capability::parse or \ref capability::buildModalias + * + * FIXME should it \throw if the resolvable does not exist? + */ + void appendModaliasDependency( const data::RecordId &resolvable_id, + zypp::Dep deptype, + capability::ModaliasCap::Ptr cap); + + /** + * Adds a Hal dependency to the store. + * + * A \ref HalCap::Ptr \a cap to be specified. Among + * which type of dependency \ref zypp::Dep it is as + * the \a deptype argument. + * + * \a resolvable_id is the resolvable Id in the CacheStore + * that will own the capability + * + * You can create the modalias capability using either + * \ref capability::parse or \ref capability::buildHal + * + * FIXME should it \throw if the resolvable does not exist? + */ + void appendHalDependency( const data::RecordId &resolvable_id, + zypp::Dep deptype, + capability::HalCap::Ptr cap ); + + /** + * Adds a unknown dependency to the store. + * + * A \ref Capability::Ptr \a cap to be specified. Among + * which type of dependency \ref zypp::Dep it is as + * the \a deptype argument. + * + * \a resolvable_id is the resolvable Id in the CacheStore + * that will own the capability + * + * You can create the capability using either + * \ref capability::parse + * + * FIXME should it \throw if the resolvable does not exist? + */ + void appendUnknownDependency( const data::RecordId &resolvable_id, + zypp::Dep deptype, + capability::CapabilityImpl::Ptr cap ); + + /** + * Insert patch RPM data into <tt>patch_packages</tt> table. + * + * \param prpm The patch RPM object to insert. + * \return Record ID of the newly inserted record. + */ + data::RecordId appendPatchRpm( const data::PatchRpm_Ptr & prpm); + + + /** + * Insert delta RPM data into <tt>delta_packages</tt> table. + * + * \param drpm The delta RPM object to insert. + * \return Record ID of the newly inserted record. + */ + data::RecordId appendDeltaRpm( const data::DeltaRpm_Ptr & drpm); + + + /** + * Returns the record id of a type + * + * Types are mostly used internally. To give concepts + * a record id to associate with. + * Examples could be arch::i386, lang::en_US + * Packages::summary, rel:>, kind::Package + * + * \note If the type entry does not exist, it will + * be created and the new inserted entry's id will + * be returned. + */ + data::RecordId lookupOrAppendType( const std::string &klass, + const std::string &name ); + + /** + * Returns the record id of a repository (Source) + * + * \param alias Unique alias for this repo + * + * \note If the repository entry does not exist, it will + * be created and the new inserted entry's id will + * be returned. + */ + data::RecordId lookupOrAppendRepository( const std::string &alias ); + + /** + * Set the resolvable shared data flag pointing to + * another resolvable. + * + * This is a hint for cache readers. If any attribute + * of a resolvable is empty, is because it is shared + * with another resolvable. + * + * \param resolvable_id Id of the resolvable. Must exists + * \param shared_id The resolvable providing the data + * This one is a weak reference, the reader should just + * try to look the data there as a hint. + * use \ref data::noRecordId to reset the value. + * + */ + void setSharedData( const data::RecordId &resolvable_id, + const data::RecordId &shared_id ); + + /** + * Append a numeric attribute to a resolvable + * \param resolvable_id Resovable Id, owner of the attribute + * \param klass Type class i.e "Package" "lang" "kind" + * \param name Type name i.e : "size" "media_number" + * \param value numeric value + */ + void appendNumericAttribute( const data::RecordId &resolvable_id, + const std::string &klass, + const std::string &name, + int value ); + + /** + * Append a translated string value to a resolvable + * \param resolvable_id Resovable Id, owner of the attribute + * \param klass Type class i.e "Package" "lang" "kind" + * \param name Type name i.e : "summary" "none" "Script" + * \param text Translated text + */ + void appendTranslatedStringAttribute( const data::RecordId &resolvable_id, + const std::string &klass, + const std::string &name, + const TranslatedText &text ); + + /** + * Append a string value to a resolvable + * \param resolvable_id Resovable Id, owner of the attribute + * \param locale locale of the text language + * \param klass Type class i.e "Package" "lang" "kind" + * \param name Type name i.e : "summary" "none" "Script" + * \param text text + */ + void appendStringAttributeTranslation( const data::RecordId &resolvable_id, + const Locale &locale, + const std::string &klass, + const std::string &name, + const std::string &text ); + + /** + * Append a string value to a resolvable + * \param resolvable_id Resovable Id, owner of the attribute + * \param klass Type class i.e "Package" "lang" "kind" + * \param name Type name i.e : "summary" "none" "Script" + * \param value string value + */ + void appendStringAttribute( const data::RecordId &resolvable_id, + const std::string &klass, + const std::string &name, + const std::string &value ); + + /** + * Append a string value to a resolvable + * \param resolvable_id Resovable Id, owner of the attribute + * \param type_id Type id, \see lookupOrAppendType + * \param value string value + */ + void appendStringAttribute( const data::RecordId &resolvable_id, + const data::RecordId &type_id, + const std::string &value ); + + + /** + * Append strings from _Container to a resolvable. + * Uses \ref zypp::str::split(_Container, std::string) with + * \ref ZConfig::cacheDBSplitJoinSeparator() as the second argument + * (a separator string) of split(). + * + * \param resolvable_id Resovable Id, owner of the attribute + * \param klass Type class i.e "Package" "lang" "kind" + * \param name Type name i.e : "summary" "none" "Script" + * \param cont The string container. + */ + template <class _Container> + void appendStringContainerAttribute( const data::RecordId &resolvable_id, + const std::string &klass, + const std::string &name, + const _Container &cont ); + + /** + * Update a known repository checksum and timestamp + * + * \note If you don't provide timestamp it defaults + * to now. + * + * It is responsability of the caller to operate with + * a valid record id. You can get one + * Using \ref lookupOrAppendRepository + * + * If the repository does not exists, nothing will happen + */ + void updateRepository( const data::RecordId &id, + const std::string &checksum, + const Date ×tamp = Date::now() ); + + /** + * \short Clean repository from cache + * + * \param id repository identifier in cache + * + * You can check existence using \ref isCached + * + * \throws CacheRecordNotFoundException if the repository + * id does not refer to a valid repository. + */ + void cleanRepository( const data::RecordId &id ); + + /** + * \short Clean repository from cache + * + * \param alias Repository unique alias + * + * You can check existence using \ref isCached + * + * \throws CacheRecordNotFoundException if the repository + * alias does not refer to a valid repository. + */ + void cleanRepository( const std::string &alias ); + + /** + * get the status of a cached repository + * + * It is responsability of the caller to operate with + * a valid record id. You can get one + * Using \ref lookupOrAppendRepository + * + * You can check existence using \ref isCached + * + * \throws CacheRecordNotFoundException if the repository + * id does not refer to a valid repository. + */ + RepoStatus repositoryStatus( const data::RecordId &id ); + + /** + * get the status of a cached repository + * + * It is responsability of the caller to operate with + * a valid alias. You can insert one + * Using \ref lookupOrAppendRepository + * + * You can check existence using \ref isCached + * + * \throws CacheRecordNotFoundException if the repository + * alias is unknown + */ + RepoStatus repositoryStatus( const std::string &alias ); + + /** + * \short Does a repository exists in cache? + * + * True if the repository is cached + */ + bool isCached( const std::string &alias ); + + /** + * \short looks the id for a repository in cache + * + * \param alias Repository unique alias + * + * \throws CacheRecordNotFoundException if the repository + * alias is unknown + */ + data::RecordId lookupRepository( const std::string &alias ); + + + /** + * Returns the record id of a file entry \a path + * + * \note If the file entry does not exist, it will + * be created and the new inserted entry's id will + * be returned. + */ + data::RecordId lookupOrAppendFile( const Pathname &path ); + + /** + * Returns the record id of a name entry \a name + * + * \note If the name entry does not exist, it will + * be created and the new inserted entry's id will + * be returned. + */ + data::RecordId lookupOrAppendName( const std::string &name ); + + /** + * Returns the record id of a directory name entry \a name + * + * \note If the directory name entry does not exist, it will + * be created and the new inserted entry's id will + * be returned. + */ + data::RecordId lookupOrAppendDirName( const std::string &name ); + + /** + * Returns the record id of a file name entry \a name + * + * \note If the file name entry does not exist, it will + * be created and the new inserted entry's id will + * be returned. + */ + data::RecordId lookupOrAppendFileName( const std::string &name ); + + protected: + /** + * Internally used function that appends a entry in + * the capabilities table for a specific capability + * entry. + */ +// data::RecordId appendDependencyEntry( const data::RecordId &, +// zypp::Dep, const Resolvable::Kind & ); + + void appendStringAttribute( const data::RecordId &resolvable_id, + const data::RecordId &lang_id, + const data::RecordId &type_id, + const std::string &value ); + + /** + * Append a numeric attribute to a resolvable + * \param resolvable_id Resovable Id, owner of the attribute + * \param type_id attribute id + * \param value numeric value + */ + void appendNumericAttribute( const data::RecordId &resolvable_id, + const data::RecordId &type_id, + int value ); + + /** + * Append a bool attribute to a resolvable. Will be stored as + * numeric 1 or 0. + * + * \param resolvable_id Resovable Id, owner of the attribute + * \param type_id attribute id + * \param value bool value + */ + void appendBooleanAttribute( const data::RecordId & resolvable_id, + const std::string & klass, + const std::string & name, + bool value); + + /** \name Detail Attributes Inserters + * These functions are used by ResolvableConsumer interface functions + * to avoid some duplication across types. + */ + //@{ + void appendResObjectAttributes( const data::RecordId &rid, + const data::ResObject_Ptr & res ); + + void appendPackageBaseAttributes(const data::RecordId & pkgid, + const data::Packagebase_Ptr & package); + //@} + + + private: + /** Implementation. */ + class Impl; + /** Pointer to implementation. */ + RW_pointer<Impl> _pimpl; + }; + } +} + +#endif + Added: trunk/libzypp/zypp/cache/CacheTypes.cc URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheTypes.cc?... ============================================================================== --- trunk/libzypp/zypp/cache/CacheTypes.cc (added) +++ trunk/libzypp/zypp/cache/CacheTypes.cc Wed Jun 6 16:44:54 2007 @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ +/** \file zypp/cache/CacheTypes.cc + * +*/ +#include <iostream> +#include "zypp/base/Logger.h" +#include "zypp/base/Exception.h" +#include "zypp/cache/sqlite3x/sqlite3x.hpp" +#include "zypp/CheckSum.h" +#include "zypp/cache/CacheTypes.h" + +using namespace std; +using namespace sqlite3x; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CacheTypes + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CacheTypes::CacheTypes + // METHOD TYPE : Ctor + // + CacheTypes::CacheTypes( const Pathname &dbdir ) + : _dbdir(dbdir) + { + refreshCache(); + } + + void CacheTypes::refreshCache() + { + try + { + sqlite3_connection con((_dbdir + "zypp.db").asString().c_str()); + con.executenonquery("PRAGMA cache_size=8000;"); + con.executenonquery("BEGIN;"); + + // get all types + sqlite3_command select_types_cmd( con, "select id,class,name from types;"); + sqlite3_reader reader = select_types_cmd.executereader(); + + while(reader.read()) + { + data::RecordId id = reader.getint64(0); + string klass = reader.getstring(1); + string name = reader.getstring(2); + if ( klass == "arch" ) + _arch_cache[id] = Arch(name); + if ( klass == "rel" ) + _rel_cache[id] = Rel(name); + if ( klass == "kind" ) + _kind_cache[id] = Resolvable::Kind(name); + if ( klass == "deptype" ) + _deptype_cache[id] = name; + } + + MIL << "archs: " << _arch_cache.size() << endl; + MIL << "rel : " << _rel_cache.size() << endl; + MIL << "kind : " << _kind_cache.size() << endl; + MIL << "deptype : " << _deptype_cache.size() << endl; + } + catch ( std::exception &e ) + { + ZYPP_THROW(Exception("Error reading types")); + } + } + + Rel CacheTypes::relationFor( const data::RecordId &id ) + { + Rel rel; + std::map<data::RecordId, Rel>::const_iterator it; + if ( (it = _rel_cache.find(id) ) != _rel_cache.end() ) + rel = it->second; + else + ZYPP_THROW(Exception("Inconsistent Rel")); + + return rel; + + } + + Resolvable::Kind CacheTypes::kindFor( const data::RecordId &id ) + { + Resolvable::Kind kind; + std::map<data::RecordId, Resolvable::Kind>::const_iterator it; + if ( (it = _kind_cache.find(id) ) != _kind_cache.end() ) + kind = it->second; + else + ZYPP_THROW(Exception("Inconsistent Kind")); + + return kind; + } + + Dep CacheTypes::deptypeFor( const data::RecordId &id ) + { + std::map<data::RecordId, string>::const_iterator it; + if ( (it = _deptype_cache.find(id) ) != _deptype_cache.end() ) + return Dep(it->second); + else + { + ERR << "deptype: " << id << endl; + ZYPP_THROW(Exception("Inconsistent deptype")); + } + } + + Arch CacheTypes::archFor( const data::RecordId &id ) + { + + Arch arch; + std::map<data::RecordId, Arch>::const_iterator it; + if ( (it = _arch_cache.find(id) ) != _arch_cache.end() ) + arch = it->second; + else + ZYPP_THROW(Exception("Inconsistent Arch")); + + return arch; + } + + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CacheTypes::~CacheTypes + // METHOD TYPE : Dtor + // + CacheTypes::~CacheTypes() + {} + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const CacheTypes & obj ) + { + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace cache + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// Added: trunk/libzypp/zypp/cache/CacheTypes.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/CacheTypes.h?r... ============================================================================== --- trunk/libzypp/zypp/cache/CacheTypes.h (added) +++ trunk/libzypp/zypp/cache/CacheTypes.h Wed Jun 6 16:44:54 2007 @@ -0,0 +1,118 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ +/** \file zypp/cache/CacheTypes.h + * +*/ +#ifndef ZYPP2_CACHE_CACHETYPES_H +#define ZYPP2_CACHE_CACHETYPES_H + +#include <iosfwd> + +#include <map> +#include <string> +#include "zypp/Rel.h" +#include "zypp/Arch.h" +#include "zypp/ResTraits.h" +#include "zypp/Dep.h" +#include "zypp/Resolvable.h" +#include "zypp/Pathname.h" +#include "zypp/data/RecordId.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CacheTypes + // + /** + * Cache types is a class that reads the dynamic types + * from the cache, and keeps them on memory. + * Then it can by asked for the type for an Id. + * + * \see CacheStore::lookupOrAppendType + */ + class CacheTypes + { + friend std::ostream & operator<<( std::ostream & str, const CacheTypes & obj ); + public: + /** + * Default ctor + * + * \param dbdir Path where the cache is located. + * + */ + CacheTypes( const Pathname &dbdir ); + + /** Dtor */ + ~CacheTypes(); + + /** + * Relation for a cache record id. + * + * \param id The id you got in a cache query + * + * \throws Exception if the id is not a valid type + */ + Rel relationFor( const data::RecordId &id ); + + /** + * Kind for a cache record id. + * + * \param id The id you got in a cache query + * + * \throws Exception if the id is not a valid type + */ + Resolvable::Kind kindFor( const data::RecordId &id ); + + /** + * Dependency type for a cache record id. + * + * \param id The id you got in a cache query + * + * \throws Exception if the id is not a valid type + */ + Dep deptypeFor( const data::RecordId &id ); + + /** + * Architecture for a cache record id. + * + * \param id The id you got in a cache query + * + * \throws Exception if the id is not a valid type + */ + Arch archFor( const data::RecordId &id ); + + public: + + private: + void refreshCache(); + + std::map<data::RecordId, Rel> _rel_cache; + std::map<data::RecordId, Resolvable::Kind> _kind_cache; + std::map<data::RecordId, std::string> _deptype_cache; + std::map<data::RecordId, Arch> _arch_cache; + Pathname _dbdir; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CacheTypes Stream output */ + std::ostream & operator<<( std::ostream & str, const CacheTypes & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace cache + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_CACHE_CACHETYPES_H Added: trunk/libzypp/zypp/cache/DESIGN-WRITE-API.txt URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/DESIGN-WRITE-A... ============================================================================== --- trunk/libzypp/zypp/cache/DESIGN-WRITE-API.txt (added) +++ trunk/libzypp/zypp/cache/DESIGN-WRITE-API.txt Wed Jun 6 16:44:54 2007 @@ -0,0 +1,147 @@ + +CACHE WRITE API DESIGN +dmacvicar@suse.de +ma@suse.de + +Background and problems +======================= + +The biggest problem when designing an API that will be used +by metadata parsers to fill a database is the fact that all +the formats read data in different order. + +YUM is flawed as it mixes descriptions and user data with +basic solver data (NVRAD [1]). But it is easy to write to a +store. + +SUSETags is on the other hand has different files for primary +and user data. + +If we consideer a simple API where we have data objects to pass +to the store: + + .------------------. + | package | + +------------------+ + | NVRAD | + +------------------+ + | summary | + +------------------+ + | other data | + +------------------+ + | description | + '------------------' + +The SQL table behind the API, has a resolvables table which stores + +|-----------------| |-----------------| +| resolvable | | package_data | +|-----------------| |-----------------| +| id | NVRAD | | package_id | +|-----------------| |-----------------| + | other data | + |-----------------| + +Inserting a package means, inserting a resolvable entry, getting a new id +for it, and then insert a new package entry and fill package_id with it. + +YUM can insert this data at the same time while parsing as it is available +at the same time. SUSETags can't, so it has to cache the NVRAD and the id, to +insert the second block when it becomes available from the translations file. + +This causes the design of the data structures to be high dependant on how the metadata +is read. + +Also + +We try to look for a solution that works well in the 99% of the cases, giving the flexibility +in the rest 1%. + +Requirements +============ + +- Allow parsers to enter metadata as they get it. +- Be reasonable fast + +The first requirement would make us unable to use fixed data transport +objects to insert data. + +If we choose a data object with certains fields, we will be going in favour +of the design of certain metadata format. + +Proposed Solution +================= + +- a basic resolvable NVRAD data object +- a dynamic fields object: + + .------------------------. + | package_data | + +------------------+-----+ + | summary | [ ] | + | description | [ ] | + | group | [ ] | + | packager | [ ] | + | license | [ ] | + '------------------+-----' + +Everytime a package object is inserted in the cache, the resolvable +entry will be inserted, but also the specific data for the resolvable +kind will be created in a empty state. The id of the resolvable will be +returned. + +The parser can then write the data passing a structure like the one +described above, where the first column represents the field and the second +the field to update. A SQL UPDATE statement will be generated from this +data object, and adding the fields for first time will be no different as +UPDATING the fields. + +This presents one problem. As the SQL is generated from the data object +actve fields, we can't precompile those update statements. This is solved easily. +We can assume if a metadata parser is inserting a combination of fields for +lot of packages, that it will use the same combination for all packages in most +of the cases. We can precompile the statements for a combination of fields and +cache them in a precompiled statement pool. When we will insert another data +block, we can lookup if a precompiled statement for the combination exists and +use it. The only cases that will not benefit from it would be updating all the +time in different orders (which will hit the cache when all field combinations are +reached). So problem has a easy solution. + +Implementation +============== + +The implementation of the data objects is not defined yet. Several alternatives +come to mind: + +struct PackageData +{ + enum Fields { + FIELD_DESCRIPTION, + FIELD_SUMMARY, + FIELD_GROUP, + }; + + string description; + string summary; + int size; + + int fields_mask; + // or set<Field> fields +}; + +struct PackageData +{ + pair<bool, string> description; + pair<bool, string> summary; + pair<bool, int> size; +}; + +In this case, we would need to know the types of the data +before writing it. + +We are investigating the use of boost::any [2] in order to see if +it is possible to make the api even easier. + + + [1]: Name Version Release Arch Deps + [2]: http://www.boost.org/doc/html/any.html \ No newline at end of file Added: trunk/libzypp/zypp/cache/ResolvableQuery.cc URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/ResolvableQuer... ============================================================================== --- trunk/libzypp/zypp/cache/ResolvableQuery.cc (added) +++ trunk/libzypp/zypp/cache/ResolvableQuery.cc Wed Jun 6 16:44:54 2007 @@ -0,0 +1,257 @@ + +#include "zypp/cache/CacheTypes.h" +#include "zypp/cache/ResolvableQuery.h" +#include "zypp/cache/sqlite3x/sqlite3x.hpp" + +using namespace sqlite3x; +using namespace std; + +namespace zypp { namespace cache { + + +struct ResolvableQuery::Impl +{ + Pathname _dbdir; + string _fields; + CacheTypes _type_cache; + + Impl( const Pathname &dbdir) + : _dbdir(dbdir) + , _type_cache(dbdir) + { + _fields = "id, name, version, release, epoch, arch, kind, installed_size, archive_size, install_only, build_time, install_time, repository_id"; + } + + ~Impl() + { + } + + + data::ResObject_Ptr fromRow( sqlite3_reader &reader ) + { + data::ResObject_Ptr ptr (new data::ResObject); + + ptr->name = reader.getstring(1); + ptr->edition = Edition( reader.getstring(2), reader.getstring(3), reader.getint(4)); + ptr->arch = _type_cache.archFor(reader.getint(5)); + + // TODO get the rest of the data + + return ptr; + } + + + void query( const data::RecordId &id, + ProcessResolvable fnc ) + { + sqlite3_connection con((_dbdir + "zypp.db").asString().c_str()); + //con.executenonquery("PRAGMA cache_size=8000;"); + con.executenonquery("BEGIN;"); + sqlite3_command cmd( con, "select " + _fields + " from resolvables where id=:id;"); + cmd.bind(":id", id); + sqlite3_reader reader = cmd.executereader(); + while(reader.read()) + { + fnc( id, fromRow(reader) ); + } + con.executenonquery("COMMIT;"); + } + + + void query( const std::string &s, + ProcessResolvable fnc ) + { + + sqlite3_connection con((_dbdir + "zypp.db").asString().c_str()); + //con.executenonquery("PRAGMA cache_size=8000;"); + con.executenonquery("BEGIN;"); + sqlite3_command cmd( con, "select " + _fields + " from resolvables where name like '%:name%';"); + cmd.bind(":name", s); + sqlite3_reader reader = cmd.executereader(); + while(reader.read()) + { + fnc( reader.getint64(0), fromRow(reader) ); + } + con.executenonquery("COMMIT;"); + } + + + std::string queryStringAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) + { + sqlite3_connection con((_dbdir + "zypp.db").asString().c_str()); + return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name); + } + + + std::string queryStringAttributeTranslation( const data::RecordId &record_id, + const Locale &locale, + const std::string &klass, + const std::string &name ) + { + sqlite3_connection con((_dbdir + "zypp.db").asString().c_str()); + return queryStringAttributeTranslationInternal( con, record_id, locale, klass, name ); + } + + + TranslatedText queryTranslatedStringAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) + { + sqlite3_connection con((_dbdir + "zypp.db").asString().c_str()); + return queryTranslatedStringAttributeInternal( con, record_id, klass, name ); + } + + + int queryNumericAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) + { + sqlite3_connection con((_dbdir + "zypp.db").asString().c_str()); + return queryNumericAttributeInternal( con, record_id, klass, name); + } + +private: + + int queryNumericAttributeInternal( sqlite3_connection &con, + const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) + { + con.executenonquery("BEGIN;"); + sqlite3_command cmd( con, "select a.value from numeric_attributes a,types t where a.weak_resolvable_id=:rid and a.attr_id=t.id and t.class=:tclass and t.name=:tname;"); + + cmd.bind(":rid", record_id); + + cmd.bind(":tclass", klass); + cmd.bind(":tname", name); + + return cmd.executeint(); + } + + TranslatedText queryTranslatedStringAttributeInternal( sqlite3_connection &con, + const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) + { + //con.executenonquery("PRAGMA cache_size=8000;"); + con.executenonquery("BEGIN;"); + sqlite3_command cmd( con, "select a.text, l.name from text_attributes a,types l,types t where a.weak_resolvable_id=:rid and a.lang_id=l.id and a.attr_id=t.id and l.class=:lclass and t.class=:tclass and t.name=:tname;"); + + cmd.bind(":rid", record_id); + cmd.bind(":lclass", "lang"); + + cmd.bind(":tclass", klass); + cmd.bind(":tname", name); + + TranslatedText result; + sqlite3_reader reader = cmd.executereader(); + while(reader.read()) + { + result.setText( reader.getstring(0), Locale( reader.getstring(1) ) ); + } + return result; + } + + std::string queryStringAttributeInternal( sqlite3_connection &con, + const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) + { + return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name); + } + + std::string queryStringAttributeTranslationInternal( sqlite3_connection &con, + const data::RecordId &record_id, + const Locale &locale, + const std::string &klass, + const std::string &name ) + { + //con.executenonquery("PRAGMA cache_size=8000;"); + con.executenonquery("BEGIN;"); + sqlite3_command cmd( con, "select a.text from text_attributes a,types l,types t where a.weak_resolvable_id=:rid and a.lang_id=l.id and a.attr_id=t.id and l.class=:lclass and l.name=:lname and t.class=:tclass and t.name=:tname;"); + + cmd.bind(":rid", record_id); + cmd.bind(":lclass", "lang"); + if (locale == Locale() ) + cmd.bind(":lname", "none"); + else + cmd.bind(":lname", locale.code()); + + cmd.bind(":tclass", klass); + cmd.bind(":tname", name); + + return cmd.executestring(); + } +}; + +////////////////////////////////////////////////////////////////////////////// +// FORWARD TO IMPLEMENTATION +////////////////////////////////////////////////////////////////////////////// + +ResolvableQuery::ResolvableQuery( const Pathname &dbdir) + : _pimpl(new Impl(dbdir)) +{ +} + +////////////////////////////////////////////////////////////////////////////// + +void ResolvableQuery::query( const data::RecordId &id, ProcessResolvable fnc ) +{ + _pimpl->query(id, fnc); +} + +////////////////////////////////////////////////////////////////////////////// + +void ResolvableQuery::query( const std::string &s, ProcessResolvable fnc ) +{ + _pimpl->query(s, fnc); +} + +////////////////////////////////////////////////////////////////////////////// + +int ResolvableQuery::queryNumericAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) +{ + return _pimpl->queryNumericAttribute(record_id, klass, name); +} + +bool ResolvableQuery::queryBooleanAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) +{ + return _pimpl->queryNumericAttribute(record_id, klass, name); +} + + +std::string ResolvableQuery::queryStringAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) +{ + return _pimpl->queryStringAttribute(record_id, klass, name); +} + +////////////////////////////////////////////////////////////////////////////// + +std::string ResolvableQuery::queryStringAttributeTranslation( const data::RecordId &record_id, + const Locale &locale, + const std::string &klass, + const std::string &name ) +{ + return _pimpl->queryStringAttributeTranslation(record_id, locale, klass, name); +} + +////////////////////////////////////////////////////////////////////////////// + +TranslatedText ResolvableQuery::queryTranslatedStringAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ) +{ + return _pimpl->queryTranslatedStringAttribute(record_id, klass, name); +} + +////////////////////////////////////////////////////////////////////////////// + +} } // namespace zypp::cache Added: trunk/libzypp/zypp/cache/ResolvableQuery.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/ResolvableQuer... ============================================================================== --- trunk/libzypp/zypp/cache/ResolvableQuery.h (added) +++ trunk/libzypp/zypp/cache/ResolvableQuery.h Wed Jun 6 16:44:54 2007 @@ -0,0 +1,141 @@ + +#ifndef ZYPP_CACHE_RESOLVABLE_QUERY_H +#define ZYPP_CACHE_RESOLVABLE_QUERY_H + +#include "zypp/base/Function.h" +#include "zypp/Pathname.h" +#include "zypp/data/ResolvableData.h" +#include "zypp/data/RecordId.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace cache + { ///////////////////////////////////////////////////////////////// + + /** + * The resolvable query class allows you to query for resolvable + * data and properties from the cache. + */ + struct ResolvableQuery + { + public: + /** + * Callback definition + * first parameter is the resolvable id. + * second parameter is a \ref data::ResObjectData object with the resource + */ + typedef function<bool( const data::RecordId &, + data::ResObject_Ptr )> ProcessResolvable; + + /** + * Constructor + * + * \param dbdir Cache location path + */ + ResolvableQuery( const Pathname &dbdir ); + + /** + * Query by record id + * \param record_id Resolvable id to query + * \param fnc callback to send the data to. (Will be called once or none) + */ + void query( const data::RecordId &record_id, + ProcessResolvable fnc ); + + /** + * Query by matching text + * \param text text to match + * \param fnc callback to send the data to. (Will be called once per result) + */ + void query( const std::string &text, + ProcessResolvable fnc ); + + /** + * Queries a specifc attribute for a resolvable + * + * \param record_id Resolvable cache id + * \param klass Attribute Class + * \param name Attribute Name + * + * \return The attribute or 0 if + * no record is found. + */ + int queryNumericAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ); + + + /** + * Queries a specifc attribute for a resolvable + * + * \param record_id Resolvable cache id + * \param klass Attribute Class + * \param name Attribute Name + * + * \return The bool value of the attribute or <tt>false</tt> + * if no record is found. + */ + bool queryBooleanAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ); + + + /** + * Queries a specifc attribute for a resolvable + * + * \param record_id Resolvable cache id + * \param klass Attribute Class + * \param name Attribute Name + * + * \return The attribute or a empty string if + * no record is found. + */ + std::string queryStringAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ); + + /** + * Queries a specifc attribute translation + * for a resolvable. + * + * \param record_id Resolvable cache id + * \param locale Locale of the translation + * \param klass Attribute Class + * \param name Attribute Name + * + * \return The attribute or a empty string if + * no record is found. + */ + std::string queryStringAttributeTranslation( const data::RecordId &record_id, + const Locale &locale, + const std::string &klass, + const std::string &name ); + + /** + * Queries all translations for a specific attribute + * in a resolvable. + * + * \param record_id Resolvable cache id + * \param klass Attribute Class + * \param name Attribute Name + * + * \return all attribute translations or a empty + * \ref TranslatedString if no record is found. + */ + TranslatedText queryTranslatedStringAttribute( const data::RecordId &record_id, + const std::string &klass, + const std::string &name ); + + private: + /** Implementation. */ + class Impl; + /** Pointer to implementation. */ + RW_pointer<Impl> _pimpl; + }; + + } //NS cache +} //NS zypp + +#endif Added: trunk/libzypp/zypp/cache/SQLITE3X-README.txt URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/SQLITE3X-READM... ============================================================================== --- trunk/libzypp/zypp/cache/SQLITE3X-README.txt (added) +++ trunk/libzypp/zypp/cache/SQLITE3X-README.txt Wed Jun 6 16:44:54 2007 @@ -0,0 +1,2 @@ + +http://s11n.net/sqlite/wrapper/overview-sqlite3x-sq3-2007.01.25.pdf Added: trunk/libzypp/zypp/cache/Utils.cpp URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/Utils.cpp?rev=... ============================================================================== --- trunk/libzypp/zypp/cache/Utils.cpp (added) +++ trunk/libzypp/zypp/cache/Utils.cpp Wed Jun 6 16:44:54 2007 @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ + +#include <vector> + +#include "zypp/base/Logger.h" +#include "zypp/base/String.h" + +#include "zypp/cache/Utils.h" + +using namespace std; + +////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +namespace cache +{ ///////////////////////////////////////////////////////////////// + +int tribool_to_int( boost::tribool b ) +{ + if (b) + return 1; + else if (!b) + return 0; + else + return 2; +} + +boost::tribool int_to_tribool( int i ) +{ + if (i==1) + return true; + else if (i==0) + return false; + else + return boost::indeterminate; +} + +std::string checksum_to_string( const CheckSum &checksum ) +{ + return checksum.type() + ":" + checksum.checksum(); +} + +CheckSum string_to_checksum( const std::string &checksum ) +{ + std::vectorstd::string words; + if ( str::split( checksum, std::back_inserter(words), ":" ) != 2 ) + return CheckSum(); + + return CheckSum( words[0], words[19]); +} + +} +} + Added: trunk/libzypp/zypp/cache/Utils.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/Utils.h?rev=56... ============================================================================== --- trunk/libzypp/zypp/cache/Utils.h (added) +++ trunk/libzypp/zypp/cache/Utils.h Wed Jun 6 16:44:54 2007 @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +---------------------------------------------------------------------*/ + +#ifndef ZYPP_DATA_UTILS_H +#define ZYPP_DATA_UTILS_H + +#include "zypp/base/Logger.h" +#include "zypp/base/String.h" +#include "zypp/CheckSum.h" +#include <boost/logic/tribool.hpp> + +////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +namespace cache +{ ///////////////////////////////////////////////////////////////// + + int tribool_to_int( boost::tribool b ); + boost::tribool int_to_tribool( int i ); + std::string checksum_to_string( const CheckSum &checksum ); + CheckSum string_to_checksum( const std::string &checksum ); + +} +} + +#endif Added: trunk/libzypp/zypp/cache/schema/DESIGN-SCHEMA.txt URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/schema/DESIGN-... ============================================================================== --- trunk/libzypp/zypp/cache/schema/DESIGN-SCHEMA.txt (added) +++ trunk/libzypp/zypp/cache/schema/DESIGN-SCHEMA.txt Wed Jun 6 16:44:54 2007 @@ -0,0 +1,3 @@ + +See: +http://en.opensuse.org/Libzypp/Refactoring/CacheSchema \ No newline at end of file Added: trunk/libzypp/zypp/cache/schema/mkarray.c URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/schema/mkarray... ============================================================================== --- trunk/libzypp/zypp/cache/schema/mkarray.c (added) +++ trunk/libzypp/zypp/cache/schema/mkarray.c Wed Jun 6 16:44:54 2007 @@ -0,0 +1,134 @@ +/* + * mkarray - make a c array containing the input file. + * + * this file is part of the makeutil package: + * http://sourceforge.net/projects/makeutil/ + * http://www.cybermesa.com/~aisa/makeutil/ + * + * this file is hereby placed in the public domain. + * aisa0@users.sourceforge.net, aisa@cybermesa.com + */ + +static char rcsid[]="$Id: mkarray.c,v 1.2 2004/12/11 18:21:51 aisa0 Exp $"; + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static +mkarray(filename, file, ofile, varname) + char *filename; + FILE *file; + FILE *ofile; + char *varname; +{ + char buf[BUFSIZ]; + size_t i, rsize, tsize=0; + int done=0, line=8, status=EXIT_SUCCESS; + + fprintf(ofile, "/*\n"); + fprintf(ofile, " * this file is automatically generated\n"); + fprintf(ofile, " */\n"); + fprintf(ofile, "\n"); + fprintf(ofile, "#include <string.h>\n"); + fprintf(ofile, "\n"); + fprintf(ofile, "static char rcsid[]="%s";\n", rcsid); + fprintf(ofile, "\n"); + fprintf(ofile, "char %s[]=\n{\n", varname); + + while(!done) { + int i, ch; + + rsize=fread(&buf[0], sizeof(char), sizeof buf/sizeof buf[0], file); + tsize+=rsize; + + switch(rsize) { + case 0: + rsize=1; + buf[0]='\0'; + done=1; + + /* down seems more likely */ + + default: + for(i=0;i<rsize;++i) { + if(8==line) fputc('\t', ofile); + + line+=(ch=fprintf(ofile, "0x%02x,", buf[i]&0xff)); + + if(line+ch>=78) { + line=8; + fputc('\n', ofile); + } + } + } + } + if(ferror(file)) { + perror("error: read"); + status|=EXIT_FAILURE; + } + + if(8!=line) fputc('\n', ofile); + fputs("};\n\n", ofile); + + fprintf(ofile, "size_t _%s_size=%d;\n", varname, tsize); + fprintf(ofile, "size_t *%s_size=&_%s_size;\n", varname, varname); + + if(ferror(ofile)) { + perror("error: write: -: "); + status|=EXIT_FAILURE; + } + if(EOF==fclose(ofile)) { + perror("error: close: -: "); + status|=EXIT_FAILURE; + } + + return status; +} + +main(argc, argv) + char *argv[]; +{ + char *filename, *ofilename, *varname; + FILE *file; + int status=EXIT_SUCCESS; + + --argc; + ++argv; + + if(argc!=3) { + fputs("usage: mkarray <input-file> <var-name> <output-file>\n", stderr); + fprintf( stderr, "You gave %d args\n", argc); + exit(status|EXIT_FAILURE); + } + + filename=argv[0]; + ofilename=argv[2]; + varname=argv[1]; + + if(0==strcmp("-", filename)) { + status|=mkarray(filename, stdin, varname); + } else { + FILE *file; + FILE *ofile; + if( ( NULL!=(file=fopen(filename, "rb")) ) && ( NULL!=(ofile=fopen(ofilename, "w")) ) ) + { + status|=mkarray(filename, file, ofile, varname); + if(EOF==fclose(file)) { + perror("error: close"); + status|=EXIT_FAILURE; + } + } + else + { + perror("error: open"); + status|=EXIT_FAILURE; + } + } + + exit(status); +} + +/* ..__ + * `' " + */ Added: trunk/libzypp/zypp/cache/schema/schema.sql URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/schema/schema.... ============================================================================== --- trunk/libzypp/zypp/cache/schema/schema.sql (added) +++ trunk/libzypp/zypp/cache/schema/schema.sql Wed Jun 6 16:44:54 2007 @@ -0,0 +1,299 @@ + +------------------------------------------------ +-- The cleanup can be generated as: +-- cat schema.sql | grep "^CREATE" | awk '{print "DROP " $2 " IF EXISTS " $3 ";"}' | sort -r +------------------------------------------------ + +DROP TRIGGER IF EXISTS remove_resolvables; +DROP TRIGGER IF EXISTS remove_patch_packages_baseversions; +DROP TABLE IF EXISTS types; +DROP TABLE IF EXISTS text_attributes; +DROP TABLE IF EXISTS split_capabilities; +DROP TABLE IF EXISTS resolvables_repositories; +DROP TABLE IF EXISTS resolvables; +DROP TABLE IF EXISTS patch_packages_baseversions; +DROP TABLE IF EXISTS patch_packages; +DROP TABLE IF EXISTS other_capabilities; +DROP TABLE IF EXISTS numeric_attributes; +DROP TABLE IF EXISTS names; +DROP TABLE IF EXISTS named_capabilities; +DROP TABLE IF EXISTS modalias_capabilities; +DROP TABLE IF EXISTS locks; +DROP TABLE IF EXISTS hal_capabilities; +DROP TABLE IF EXISTS files; +DROP TABLE IF EXISTS file_names; +DROP TABLE IF EXISTS file_capabilities; +DROP TABLE IF EXISTS dir_names; +DROP TABLE IF EXISTS delta_packages; +DROP TABLE IF EXISTS db_info; +DROP TABLE IF EXISTS repositories; +DROP INDEX IF EXISTS types_class_name_index; +DROP INDEX IF EXISTS text_attributes_index; +DROP INDEX IF EXISTS numeric_attributes_index; +DROP INDEX IF EXISTS named_capabilities_name; + +------------------------------------------------ +-- version metadata, probably not needed, there +-- is pragma user_version +------------------------------------------------ + +CREATE TABLE db_info ( + version INTEGER +); + +------------------------------------------------ +-- Basic types like archs, attributes, languages +------------------------------------------------ + +CREATE TABLE types ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , class TEXT NOT NULL + , name TEXT NOT NULL +); +CREATE INDEX types_class_name_index ON types(class, name); + +------------------------------------------------ +-- Knew repositories. They existed some day. +------------------------------------------------ + +CREATE TABLE repositories ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , alias TEXT NOT NULL UNIQUE + , checksum TEXT DEFAULT NULL + , timestamp INTEGER NOT NULL +); +CREATE INDEX repo_alias_index ON repositories(alias); + +------------------------------------------------ +-- Resolvable names +------------------------------------------------ + +CREATE TABLE names ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , name TEXT UNIQUE +); + +------------------------------------------------ +-- File names table and normalized sub tables +------------------------------------------------ + +CREATE TABLE file_names ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , name TEXT +); + +CREATE TABLE dir_names ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , name TEXT +); + +CREATE TABLE files ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , dir_name_id INTEGER NOT NULL + , file_name_id INTEGER NOT NULL + , UNIQUE ( dir_name_id, file_name_id ) +); + +------------------------------------------------ +-- Resolvables table +------------------------------------------------ + +-- Resolvables translated strings +CREATE TABLE text_attributes ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , weak_resolvable_id INTEGER NOT NULL + , lang_id INTEGER REFERENCES types(id) + , attr_id INTEGER REFERENCES types(id) + , text TEXT +); +CREATE INDEX text_attributes_index ON text_attributes(weak_resolvable_id, lang_id, attr_id); + +-- Resolvables numeric attributes +CREATE TABLE numeric_attributes ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , weak_resolvable_id INTEGER NOT NULL + , attr_id INTEGER REFERENCES types(id) + , value INTEGER NOT NULL +); +CREATE INDEX numeric_attributes_index ON numeric_attributes(weak_resolvable_id, attr_id); + + +CREATE TABLE resolvables ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , name TEXT + , version TEXT + , release TEXT + , epoch INTEGER + , arch INTEGER REFERENCES types(id) + , kind INTEGER REFERENCES types(id) + , repository_id INTEGER REFERENCES repositories(id) + , installed_size INTEGER + , archive_size INTEGER + , install_only INTEGER + , build_time INTEGER + , install_time INTEGER + , shared_id INTEGER DEFAULT NULL +); +CREATE INDEX resolvable_repository_id ON resolvables(repository_id); + +------------------------------------------------ +-- Do we need those here? +------------------------------------------------ + +CREATE TABLE locks ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , name TEXT + , version TEXT + , release TEXT + , epoch INTEGER + , arch INTEGER + , relation INTEGER + , repository TEXT + , glob TEXT + , importance INTEGER + , importance_gteq INTEGER + +); + +CREATE TABLE delta_packages ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , media_nr INTEGER + , location TEXT + , checksum TEXT + , download_size INTEGER + , build_time INTEGER + , baseversion_version TEXT + , baseversion_release TEXT + , baseversion_epoch INTEGER + , baseversion_checksum TEXT + , baseversion_build_time INTEGER + , baseversion_sequence_info TEXT + +); + +CREATE TABLE patch_packages ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , media_nr INTEGER + , location TEXT + , checksum TEXT + , download_size INTEGER + , build_time INTEGER + +); + +CREATE TABLE patch_packages_baseversions ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , patch_package_id INTEGER REFERENCES patch_packages(id) + , version TEXT + , release TEXT + , epoch INTEGER + +); + +------------------------------------------------ +-- Capabilities +------------------------------------------------ + +CREATE TABLE named_capabilities ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , resolvable_id INTEGER REFERENCES resolvables(id) + , dependency_type INTEGER + , refers_kind INTEGER + , name_id INTEGER REFERENCES names(id) + , version TEXT + , release TEXT + , epoch INTEGER + , relation INTEGER +); +CREATE INDEX named_capabilities_name ON named_capabilities(name_id); +CREATE INDEX named_capabilities_resolvable ON named_capabilities(resolvable_id); + +CREATE TABLE modalias_capabilities ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , resolvable_id INTEGER REFERENCES resolvables(id) + , dependency_type INTEGER + , refers_kind INTEGER + , name TEXT + , value TEXT + , relation INTEGER +); +CREATE INDEX modalias_capabilities_resolvable ON modalias_capabilities(resolvable_id); + +CREATE TABLE hal_capabilities ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , resolvable_id INTEGER REFERENCES resolvables(id) + , dependency_type INTEGER + , refers_kind INTEGER + , name TEXT + , value TEXT + , relation INTEGER +); + +CREATE TABLE file_capabilities ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , resolvable_id INTEGER REFERENCES resolvables(id) + , dependency_type INTEGER + , refers_kind INTEGER + , file_id INTEGER REFERENCES files(id) +); +CREATE INDEX file_capabilities_resolvable ON file_capabilities(resolvable_id); + +CREATE TABLE other_capabilities ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , resolvable_id INTEGER REFERENCES resolvables(id) + , dependency_type INTEGER + , refers_kind INTEGER + , value TEXT +); +CREATE INDEX other_capabilities_resolvable ON other_capabilities(resolvable_id); + +CREATE TABLE split_capabilities ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL + , resolvable_id INTEGER REFERENCES resolvables(id) + , dependency_type INTEGER + , refers_kind INTEGER + , name_id INTEGER REFERENCES names(id) + , file_id INTEGER REFERENCES files(id) +); +CREATE INDEX split_capabilities_resolvable ON split_capabilities(resolvable_id); + +-- Auto clean capabilities +CREATE TRIGGER remove_resolvables + AFTER DELETE ON resolvables + BEGIN + DELETE FROM named_capabilities WHERE resolvable_id = old.id; + DELETE FROM modalias_capabilities WHERE resolvable_id = old.id; + DELETE FROM hal_capabilities WHERE resolvable_id = old.id; + DELETE FROM file_capabilities WHERE resolvable_id = old.id; + DELETE FROM split_capabilities WHERE resolvable_id = old.id; + DELETE FROM other_capabilities WHERE resolvable_id = old.id; + END; + +------------------------------------------------ +-- Associate resolvables and repositories +------------------------------------------------ + +-- FIXME do we want to allow same resolvable to +-- be listed twice in same source but different +-- medias? I think NOT. +CREATE TABLE resolvables_repositories ( + resolvable_id INTEGER REFERENCES resolvables (id) + , repository_id INTEGER REFERENCES repositories (id) + , repository_media_nr INTEGER + , PRIMARY KEY ( resolvable_id, repository_id ) +); + +-- Auto clean repositories +CREATE TRIGGER remove_repositories + AFTER DELETE ON repositories + BEGIN + DELETE FROM resolvables WHERE repository_id = old.id; + END; + +CREATE TRIGGER remove_patch_packages_baseversions + AFTER DELETE ON patch_packages + BEGIN + DELETE FROM patch_packages_baseversions WHERE patch_package_id = old.id; + END; + + Added: trunk/libzypp/zypp/cache/sqlite3x/sqlite3x.hpp URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/cache/sqlite3x/sqlit... ============================================================================== --- trunk/libzypp/zypp/cache/sqlite3x/sqlite3x.hpp (added) +++ trunk/libzypp/zypp/cache/sqlite3x/sqlite3x.hpp Wed Jun 6 16:44:54 2007 @@ -0,0 +1,199 @@ +/* + Copyright (C) 2004-2005 Cory Nelson + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution-- To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org For additional commands, e-mail: zypp-commit+help@opensuse.org