diff options
author | Timo Teräs <timo.teras@iki.fi> | 2012-02-22 08:45:40 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2012-02-22 08:45:40 +0200 |
commit | bf82e2e5fd45f4ba425a128ae4fdb6144c82f218 (patch) | |
tree | b7d97e0aede851d3d0222ee30141cb00bccf217f /src/database.c | |
parent | 568d57336d84179b3e97a301872890dc51969a36 (diff) | |
download | apk-tools-bf82e2e5fd45f4ba425a128ae4fdb6144c82f218.tar.gz apk-tools-bf82e2e5fd45f4ba425a128ae4fdb6144c82f218.tar.bz2 apk-tools-bf82e2e5fd45f4ba425a128ae4fdb6144c82f218.tar.xz apk-tools-bf82e2e5fd45f4ba425a128ae4fdb6144c82f218.zip |
db, solver, io: scan cache items at startup
It is faster to just scan the cache directory for existing packages
at startup than trying to faccessat() them on demand. It also makes
quite a few parts of the code more readable and simpler.
Diffstat (limited to 'src/database.c')
-rw-r--r-- | src/database.c | 105 |
1 files changed, 80 insertions, 25 deletions
diff --git a/src/database.c b/src/database.c index e6945c3..19dc837 100644 --- a/src/database.c +++ b/src/database.c @@ -1091,9 +1091,10 @@ static int apk_db_index_write_nr_cache(struct apk_database *db) ctx.os = os; list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) { - if (ipkg->pkg->repos != 0) + struct apk_package *pkg = ipkg->pkg; + if (pkg->repos != 0 || !pkg->in_cache) continue; - r = write_index_entry(ipkg->pkg, &ctx); + r = write_index_entry(pkg, &ctx); if (r != 0) return r; } @@ -1223,6 +1224,14 @@ static void relocate_database(struct apk_database *db) apk_move_file(db->root_fd, apk_installed_file_old, apk_installed_file); } +static void mark_in_cache(struct apk_database *db, const char *name, struct apk_package *pkg) +{ + if (pkg == NULL) + return; + + pkg->in_cache = 1; +} + int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) { const char *msg = NULL; @@ -1245,8 +1254,8 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_hash_init(&db->available.names, &pkg_name_hash_ops, 4000); apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 10000); - apk_hash_init(&db->installed.dirs, &dir_hash_ops, 10000); - apk_hash_init(&db->installed.files, &file_hash_ops, 20000); + apk_hash_init(&db->installed.dirs, &dir_hash_ops, 5000); + apk_hash_init(&db->installed.files, &file_hash_ops, 100000); list_init(&db->installed.packages); list_init(&db->installed.triggers); apk_dependency_array_init(&db->world); @@ -1400,6 +1409,9 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_db_index_write_nr_cache(db); } + if (apk_db_cache_active(db)) + apk_db_cache_foreach_item(db, mark_in_cache); + if (db->compat_newfeatures) { apk_warning("This apk-tools is OLD! Some packages %s.", db->compat_notinstallable ? @@ -1613,6 +1625,48 @@ int apk_db_cache_active(struct apk_database *db) return db->cache_dir != apk_static_cache_dir; } +struct foreach_cache_item_ctx { + struct apk_database *db; + apk_cache_item_cb cb; +}; + +static int foreach_cache_file(void *pctx, const char *name) +{ + struct foreach_cache_item_ctx *ctx = (struct foreach_cache_item_ctx *) pctx; + struct apk_database *db = ctx->db; + struct apk_package *pkg = NULL; + apk_blob_t b = APK_BLOB_STR(name), bname, bver; + int i; + + if (apk_pkg_parse_name(b, &bname, &bver) == 0) { + /* Package - search for it */ + struct apk_name *name = apk_db_get_name(db, bname); + char tmp[PATH_MAX]; + if (name == NULL) + goto no_pkg; + for (i = 0; i < name->pkgs->num; i++) { + struct apk_package *pkg0 = name->pkgs->item[i]; + + apk_pkg_format_cache(pkg0, APK_BLOB_BUF(tmp)); + if (apk_blob_compare(b, APK_BLOB_STR(tmp)) == 0) { + pkg = pkg0; + break; + } + } + } +no_pkg: + ctx->cb(db, name, pkg); + + return 0; +} + +int apk_db_cache_foreach_item(struct apk_database *db, apk_cache_item_cb cb) +{ + struct foreach_cache_item_ctx ctx = { db, cb }; + + return apk_dir_foreach_file(dup(db->cache_fd), foreach_cache_file, &ctx); +} + int apk_db_permanent(struct apk_database *db) { return db->permanent; @@ -1685,7 +1739,7 @@ int apk_repo_format_filename(char *buf, size_t len, return n; } -static int apk_repo_is_remote(struct apk_repository *repo) +int apk_repo_is_remote(struct apk_repository *repo) { return repo->csum.type != APK_CHECKSUM_NONE; } @@ -1722,30 +1776,29 @@ struct apk_repository *apk_db_select_repo(struct apk_database *db, unsigned int repos = pkg->repos & ~(db->bad_repos); int i; - /* Always prefer local repositories */ - if ((repos & db->local_repos) != 0) + /* Uninstalled and unavailable? */ + if (repos == 0 && pkg->ipkg == NULL) + return NULL; + + if ((repos & db->local_repos) == 0) { + /* Network repository (or installed and unavailable) */ + if (apk_flags & APK_NO_NETWORK) { + if (pkg->in_cache) + return &cache_repo; + return NULL; + } + } else { + /* Local repositories; don't use network */ repos &= db->local_repos; + } /* Pick first repository providing this package */ - for (i = 0; i < APK_MAX_REPOS; i++) + for (i = 0; i < APK_MAX_REPOS; i++) { if (repos & BIT(i)) - break; - - /* If this is a remote repository, and we have no network, - * check that we have it in cache */ - if ((i >= APK_MAX_REPOS) || - ((db->local_repos & BIT(i)) == 0 && (apk_flags & APK_NO_NETWORK))) { - char cacheitem[PATH_MAX]; - - apk_pkg_format_cache(pkg, APK_BLOB_BUF(cacheitem)); - if (faccessat(db->cache_fd, cacheitem, R_OK, 0) != 0) - return NULL; + return &db->repos[i]; } - if (i >= APK_MAX_REPOS) - return &cache_repo; - - return &db->repos[i]; + return NULL; } int apk_repository_update(struct apk_database *db, struct apk_repository *repo) @@ -2347,10 +2400,12 @@ static int apk_db_unpack_pkg(struct apk_database *db, tar->close(tar); if (need_copy) { - if (r == 0) + if (r == 0) { renameat(db->cachetmp_fd, item, db->cache_fd, item); - else + pkg->in_cache = 1; + } else { unlinkat(db->cachetmp_fd, item, 0); + } } if (r != 0) { |