1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-08-27 21:50:15 +03:00

shared/install: optionally cache the preset list

When doing list-unit-files with --root, we would re-read the preset
list for every unit. This uses a cache to only do it once. The time
for list-unit-files goes down by about ~30%.

unit_file_query_preset() is also called from src/core/. This patch does not
touch that path, since the saving there are smaller, since preset status is
only read on demand over dbus, and caching would be more complicated.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2020-04-30 22:37:34 +02:00
parent c39b7821f6
commit 8f7b256665
4 changed files with 46 additions and 36 deletions

View File

@ -4267,7 +4267,8 @@ int unit_get_unit_file_preset(Unit *u) {
u->unit_file_preset = unit_file_query_preset(
u->manager->unit_file_scope,
NULL,
basename(u->fragment_path));
basename(u->fragment_path),
NULL);
return u->unit_file_preset;
}

View File

@ -55,16 +55,11 @@ typedef enum {
PRESET_DISABLE,
} PresetAction;
typedef struct {
struct UnitFilePresetRule {
char *pattern;
PresetAction action;
char **instances;
} PresetRule;
typedef struct {
PresetRule *rules;
size_t n_rules;
} Presets;
};
static bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) {
assert(i);
@ -80,7 +75,7 @@ static bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) {
return !strv_isempty(i->also);
}
static void presets_freep(Presets *p) {
void unit_file_presets_freep(UnitFilePresets *p) {
size_t i;
if (!p)
@ -2913,8 +2908,8 @@ static int presets_find_config(UnitFileScope scope, const char *root_dir, char *
return conf_files_list_strv(files, ".preset", root_dir, 0, dirs);
}
static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
_cleanup_(presets_freep) Presets ps = {};
static int read_presets(UnitFileScope scope, const char *root_dir, UnitFilePresets *presets) {
_cleanup_(unit_file_presets_freep) UnitFilePresets ps = {};
size_t n_allocated = 0;
_cleanup_strv_free_ char **files = NULL;
char **p;
@ -2942,7 +2937,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
for (;;) {
_cleanup_free_ char *line = NULL;
PresetRule rule = {};
UnitFilePresetRule rule = {};
const char *parameter;
char *l;
@ -2972,7 +2967,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
continue;
}
rule = (PresetRule) {
rule = (UnitFilePresetRule) {
.pattern = unit_name,
.action = PRESET_ENABLE,
.instances = instances,
@ -2987,7 +2982,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
if (!pattern)
return -ENOMEM;
rule = (PresetRule) {
rule = (UnitFilePresetRule) {
.pattern = pattern,
.action = PRESET_DISABLE,
};
@ -3005,14 +3000,15 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
}
}
ps.initialized = true;
*presets = ps;
ps = (Presets){};
ps = (UnitFilePresets){};
return 0;
}
static int pattern_match_multiple_instances(
const PresetRule rule,
const UnitFilePresetRule rule,
const char *unit_name,
char ***ret) {
@ -3066,17 +3062,17 @@ static int pattern_match_multiple_instances(
return 0;
}
static int query_presets(const char *name, const Presets presets, char ***instance_name_list) {
static int query_presets(const char *name, const UnitFilePresets *presets, char ***instance_name_list) {
PresetAction action = PRESET_UNKNOWN;
size_t i;
char **s;
if (!unit_name_is_valid(name, UNIT_NAME_ANY))
return -EINVAL;
for (i = 0; i < presets.n_rules; i++)
if (pattern_match_multiple_instances(presets.rules[i], name, instance_name_list) > 0 ||
fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
action = presets.rules[i].action;
for (i = 0; i < presets->n_rules; i++)
if (pattern_match_multiple_instances(presets->rules[i], name, instance_name_list) > 0 ||
fnmatch(presets->rules[i].pattern, name, FNM_NOESCAPE) == 0) {
action = presets->rules[i].action;
break;
}
@ -3099,15 +3095,19 @@ static int query_presets(const char *name, const Presets presets, char ***instan
}
}
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
_cleanup_(presets_freep) Presets presets = {};
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name, UnitFilePresets *cached) {
_cleanup_(unit_file_presets_freep) UnitFilePresets tmp = {};
int r;
r = read_presets(scope, root_dir, &presets);
if (r < 0)
return r;
if (!cached)
cached = &tmp;
if (!cached->initialized) {
r = read_presets(scope, root_dir, cached);
if (r < 0)
return r;
}
return query_presets(name, presets, NULL);
return query_presets(name, cached, NULL);
}
static int execute_preset(
@ -3162,7 +3162,7 @@ static int preset_prepare_one(
InstallContext *minus,
LookupPaths *paths,
const char *name,
Presets presets,
const UnitFilePresets *presets,
UnitFileChange **changes,
size_t *n_changes) {
@ -3221,7 +3221,7 @@ int unit_file_preset(
_cleanup_(install_context_done) InstallContext plus = {}, minus = {};
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(presets_freep) Presets presets = {};
_cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
const char *config_path;
char **i;
int r;
@ -3243,7 +3243,7 @@ int unit_file_preset(
return r;
STRV_FOREACH(i, files) {
r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes);
r = preset_prepare_one(scope, &plus, &minus, &paths, *i, &presets, changes, n_changes);
if (r < 0)
return r;
}
@ -3261,7 +3261,7 @@ int unit_file_preset_all(
_cleanup_(install_context_done) InstallContext plus = {}, minus = {};
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(presets_freep) Presets presets = {};
_cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
const char *config_path = NULL;
char **i;
int r;
@ -3305,7 +3305,7 @@ int unit_file_preset_all(
continue;
/* we don't pass changes[] in, because we want to handle errors on our own */
r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0);
r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, &presets, NULL, 0);
if (r == -ERFKILL)
r = unit_file_changes_add(changes, n_changes,
UNIT_FILE_IS_MASKED, de->d_name, NULL);

View File

@ -189,7 +189,16 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang
int unit_file_verify_alias(const UnitFileInstallInfo *i, const char *dst, char **ret_dst);
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name);
typedef struct UnitFilePresetRule UnitFilePresetRule;
typedef struct {
UnitFilePresetRule *rules;
size_t n_rules;
bool initialized;
} UnitFilePresets;
void unit_file_presets_freep(UnitFilePresets *p);
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name, UnitFilePresets *cached);
const char *unit_file_state_to_string(UnitFileState s) _const_;
UnitFileState unit_file_state_from_string(const char *s) _pure_;

View File

@ -1443,7 +1443,7 @@ static bool output_show_unit_file(const UnitFileList *u, char **states, char **p
static int output_unit_file_list(const UnitFileList *units, unsigned c) {
_cleanup_(table_unrefp) Table *table = NULL;
const UnitFileList *u;
_cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
int r;
table = table_new("unit file", "state", "vendor preset");
@ -1454,7 +1454,7 @@ static int output_unit_file_list(const UnitFileList *units, unsigned c) {
if (arg_full)
table_set_width(table, 0);
for (u = units; u < units + c; u++) {
for (const UnitFileList *u = units; u < units + c; u++) {
const char *on_underline = NULL, *on_unit_color = NULL, *id;
const char *on_preset_color = NULL, *unit_preset_str;
bool underline;
@ -1478,7 +1478,7 @@ static int output_unit_file_list(const UnitFileList *units, unsigned c) {
id = basename(u->path);
r = unit_file_query_preset(arg_scope, arg_root, id);
r = unit_file_query_preset(arg_scope, arg_root, id, &presets);
if (r < 0) {
unit_preset_str = "n/a";
on_preset_color = underline ? on_underline : ansi_normal();