database: extract common method to handle machine id and architecture
authorIgor V. Kovalenko <igor.v.kovalenko@gmail.com>
Sun, 29 Nov 2020 08:21:29 +0000 (11:21 +0300)
committerPulseAudio Marge Bot <pulseaudio-maintainers@lists.freedesktop.org>
Thu, 7 Jan 2021 23:27:16 +0000 (23:27 +0000)
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/425>

12 files changed:
src/Makefile.am
src/modules/module-card-restore.c
src/modules/module-device-manager.c
src/modules/module-device-restore.c
src/modules/module-equalizer-sink.c
src/modules/module-stream-restore.c
src/pulsecore/database-gdbm.c
src/pulsecore/database-simple.c
src/pulsecore/database-tdb.c
src/pulsecore/database.c [new file with mode: 0644]
src/pulsecore/database.h
src/pulsecore/meson.build

index 97c9dce..14c5956 100644 (file)
@@ -1042,7 +1042,7 @@ libpulsecore_@PA_MAJORMINOR@_la_SOURCES = \
                pulsecore/source.c pulsecore/source.h \
                pulsecore/start-child.c pulsecore/start-child.h \
                pulsecore/thread-mq.c pulsecore/thread-mq.h \
-               pulsecore/database.h
+               pulsecore/database.c pulsecore/database.h
 
 libpulsecore_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) $(LIBSNDFILE_CFLAGS) $(WINSOCK_CFLAGS)
 libpulsecore_@PA_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) $(AM_LIBLDFLAGS) -avoid-version
index 80506cd..b35cf3e 100644 (file)
@@ -618,7 +618,7 @@ static pa_hook_result_t card_preferred_port_changed_callback(pa_core *core, pa_c
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
-    char *fname;
+    char *state_path;
     bool restore_bluetooth_profile;
 
     pa_assert(m);
@@ -648,17 +648,15 @@ int pa__init(pa_module*m) {
     pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_added_callback, u);
     pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) port_offset_change_callback, u);
 
-    if (!(fname = pa_state_path("card-database", true)))
+    if (!(state_path = pa_state_path(NULL, true)))
         goto fail;
 
-    if (!(u->database = pa_database_open(fname, true))) {
-        pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
-        pa_xfree(fname);
+    if (!(u->database = pa_database_open(state_path, "card-database", true, true))) {
+        pa_xfree(state_path);
         goto fail;
     }
 
-    pa_log_info("Successfully opened database file '%s'.", fname);
-    pa_xfree(fname);
+    pa_xfree(state_path);
 
     pa_modargs_free(ma);
     return 0;
index 308ef0b..b51b6c8 100644 (file)
@@ -1544,7 +1544,7 @@ struct prioritised_indexes {
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
-    char *fname;
+    char *state_path;
     pa_sink *sink;
     pa_source *source;
     uint32_t idx;
@@ -1601,17 +1601,15 @@ int pa__init(pa_module*m) {
         u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) source_unlink_hook_callback, u);
     }
 
-    if (!(fname = pa_state_path("device-manager", true)))
+    if (!(state_path = pa_state_path(NULL, true)))
         goto fail;
 
-    if (!(u->database = pa_database_open(fname, true))) {
-        pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
-        pa_xfree(fname);
+    if (!(u->database = pa_database_open(state_path, "device-manager", true, true))) {
+        pa_xfree(state_path);
         goto fail;
     }
 
-    pa_log_info("Successfully opened database file '%s'.", fname);
-    pa_xfree(fname);
+    pa_xfree(state_path);
 
     /* Attempt to inject the devices into the list in priority order */
     total_devices = PA_MAX(pa_idxset_size(m->core->sinks), pa_idxset_size(m->core->sources));
index 684c836..9ca2a7c 100644 (file)
@@ -1202,7 +1202,7 @@ static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_nati
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
-    char *fname;
+    char *state_path;
     pa_sink *sink;
     pa_source *source;
     uint32_t idx;
@@ -1259,17 +1259,15 @@ int pa__init(pa_module*m) {
     if (restore_formats)
         pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_EARLY, (pa_hook_cb_t) sink_put_hook_callback, u);
 
-    if (!(fname = pa_state_path("device-volumes", true)))
+    if (!(state_path = pa_state_path(NULL, true)))
         goto fail;
 
-    if (!(u->database = pa_database_open(fname, true))) {
-        pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
-        pa_xfree(fname);
+    if (!(u->database = pa_database_open(state_path, "device-volumes", true, true))) {
+        pa_xfree(state_path);
         goto fail;
     }
 
-    pa_log_info("Successfully opened database file '%s'.", fname);
-    pa_xfree(fname);
+    pa_xfree(state_path);
 
     PA_IDXSET_FOREACH(sink, m->core->sinks, idx)
         subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
index 4cfe3ed..f8a9e95 100644 (file)
@@ -946,7 +946,7 @@ static void save_state(struct userdata *u) {
     float *H;
     pa_datum key, data;
     pa_database *database;
-    char *dbname;
+    char *state_path;
     char *packed;
     size_t packed_length;
 
@@ -969,9 +969,9 @@ static void save_state(struct userdata *u) {
     data.data = state;
     data.size = filter_state_size + packed_length;
     //thread safety for 0.9.17?
-    pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, false));
-    pa_assert_se(database = pa_database_open(dbname, true));
-    pa_xfree(dbname);
+    pa_assert_se(state_path = pa_state_path(NULL, false));
+    pa_assert_se(database = pa_database_open(state_path, EQ_STATE_DB, false, true));
+    pa_xfree(state_path);
 
     pa_database_set(database, &key, &data, true);
     pa_database_sync(database);
@@ -1020,10 +1020,10 @@ static void load_state(struct userdata *u) {
     float *H;
     pa_datum key, value;
     pa_database *database;
-    char *dbname;
-    pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, false));
-    database = pa_database_open(dbname, false);
-    pa_xfree(dbname);
+    char *state_path;
+    pa_assert_se(state_path = pa_state_path(NULL, false));
+    database = pa_database_open(state_path, EQ_STATE_DB, false, false);
+    pa_xfree(state_path);
     if (!database) {
         pa_log("No resume state");
         return;
@@ -1626,12 +1626,12 @@ void dbus_init(struct userdata *u) {
     sink_list = pa_shared_get(u->sink->core, SINKLIST);
     u->database = pa_shared_get(u->sink->core, EQDB);
     if (sink_list == NULL) {
-        char *dbname;
+        char *state_path;
         sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func);
         pa_shared_set(u->sink->core, SINKLIST, sink_list);
-        pa_assert_se(dbname = pa_state_path("equalizer-presets", false));
-        pa_assert_se(u->database = pa_database_open(dbname, true));
-        pa_xfree(dbname);
+        pa_assert_se(state_path = pa_state_path(NULL, false));
+        pa_assert_se(u->database = pa_database_open(state_path, "equalizer-presets", false, true));
+        pa_xfree(state_path);
         pa_shared_set(u->sink->core, EQDB, u->database);
         pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->sink->core);
         pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
index d26543b..3153607 100644 (file)
@@ -2266,7 +2266,7 @@ static void clean_up_db(struct userdata *u) {
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
-    char *fname;
+    char *state_path;
     pa_sink_input *si;
     pa_source_output *so;
     uint32_t idx;
@@ -2324,17 +2324,15 @@ int pa__init(pa_module*m) {
         pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_fixate_hook_callback, u);
     }
 
-    if (!(fname = pa_state_path("stream-volumes", true)))
+    if (!(state_path = pa_state_path(NULL, true)))
         goto fail;
 
-    if (!(u->database = pa_database_open(fname, true))) {
-        pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
-        pa_xfree(fname);
+    if (!(u->database = pa_database_open(state_path, "stream-volumes", true, true))) {
+        pa_xfree(state_path);
         goto fail;
     }
 
-    pa_log_info("Successfully opened database file '%s'.", fname);
-    pa_xfree(fname);
+    pa_xfree(state_path);
 
     clean_up_db(u);
 
index b1da9df..cd03405 100644 (file)
@@ -59,17 +59,24 @@ void pa_datum_free(pa_datum *d) {
     pa_zero(d);
 }
 
-pa_database* pa_database_open(const char *fn, bool for_write) {
+const char* pa_database_get_arch_suffix(void) {
+    /* We include the host identifier in the file name because gdbm
+     * files are CPU dependent, and we don't want things to go wrong
+     * if we are on a multiarch system. */
+
+    return CANONICAL_HOST;
+}
+
+const char* pa_database_get_filename_suffix(void) {
+    return ".gdbm";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
     GDBM_FILE f;
     int gdbm_cache_size;
-    char *path;
 
-    pa_assert(fn);
+    pa_assert(path);
 
-    /* We include the host identifier in the file name because gdbm
-     * files are CPU dependent, and we don't want things to go wrong
-     * if we are on a multiarch system. */
-    path = pa_sprintf_malloc("%s."CANONICAL_HOST".gdbm", fn);
     errno = 0;
 
     /* We need to set the block size explicitly here, since otherwise
@@ -80,8 +87,6 @@ pa_database* pa_database_open(const char *fn, bool for_write) {
     if (f)
         pa_log_debug("Opened GDBM database '%s'", path);
 
-    pa_xfree(path);
-
     if (!f) {
         if (errno == 0)
             errno = EIO;
index 3876487..ebfbe4c 100644 (file)
@@ -222,14 +222,21 @@ static int fill_data(simple_data *db, FILE *f) {
     return pa_hashmap_size(db->map);
 }
 
-pa_database* pa_database_open(const char *fn, bool for_write) {
+const char* pa_database_get_arch_suffix(void) {
+    /* Simple database binary file format is CPU dependent. */
+    return CANONICAL_HOST;
+}
+
+const char* pa_database_get_filename_suffix(void) {
+    return ".simple";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
     FILE *f;
-    char *path;
     simple_data *db;
 
-    pa_assert(fn);
+    pa_assert(path);
 
-    path = pa_sprintf_malloc("%s."CANONICAL_HOST".simple", fn);
     errno = 0;
 
     f = pa_fopen_cloexec(path, "r");
@@ -251,8 +258,6 @@ pa_database* pa_database_open(const char *fn, bool for_write) {
         db = NULL;
     }
 
-    pa_xfree(path);
-
     return (pa_database*) db;
 }
 
index 282f580..5e73159 100644 (file)
@@ -97,18 +97,23 @@ finish:
     return c;
 }
 
-pa_database* pa_database_open(const char *fn, bool for_write) {
+const char* pa_database_get_arch_suffix(void) {
+    /* TDB binary file format is not dependent on system architecture */
+    return NULL;
+}
+
+const char* pa_database_get_filename_suffix(void) {
+    return ".tdb";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
     struct tdb_context *c;
-    char *path;
 
-    pa_assert(fn);
+    pa_assert(path);
 
-    path = pa_sprintf_malloc("%s.tdb", fn);
     if ((c = tdb_open_cloexec(path, 0, TDB_NOSYNC|TDB_NOLOCK, (for_write ? O_RDWR|O_CREAT : O_RDONLY), 0644)))
         pa_log_debug("Opened TDB database '%s'", path);
 
-    pa_xfree(path);
-
     if (!c) {
         if (errno == 0)
             errno = EIO;
diff --git a/src/pulsecore/database.c b/src/pulsecore/database.c
new file mode 100644 (file)
index 0000000..11f3d03
--- /dev/null
@@ -0,0 +1,72 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2020 Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/log.h>
+
+#include "database.h"
+#include "core-error.h"
+
+pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write) {
+
+    const char *arch_suffix = pa_database_get_arch_suffix();
+    const char *filename_suffix = pa_database_get_filename_suffix();
+
+    char *machine_id = NULL, *filename_prefix, *full_path;
+
+    pa_database *f;
+
+    pa_assert(!arch_suffix || arch_suffix[0]);
+    pa_assert(filename_suffix && filename_suffix[0]);
+
+    if (prependmid && !(machine_id = pa_machine_id())) {
+        return NULL;
+    }
+
+    /* We include the host identifier in the file name because some database files are
+     * CPU dependent, and we don't want things to go wrong if we are on a multiarch system. */
+    filename_prefix = pa_sprintf_malloc("%s%s%s%s%s",
+            machine_id?:"", machine_id?"-":"",
+            fn,
+            arch_suffix?".":"", arch_suffix?:"");
+
+    full_path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s%s", path, filename_prefix, filename_suffix);
+
+    f = pa_database_open_internal(full_path, for_write);
+
+    if (f)
+        pa_log_info("Successfully opened '%s' database file '%s'.", fn, full_path);
+    else
+        pa_log("Failed to open '%s' database file '%s': %s", fn, full_path, pa_cstrerror(errno));
+
+    pa_xfree(full_path);
+    pa_xfree(filename_prefix);
+
+    /* deallocate machine_id if it was used to construct file name */
+    pa_xfree(machine_id);
+
+    return f;
+}
index 3a1c7ce..fe28905 100644 (file)
@@ -38,8 +38,17 @@ typedef struct pa_datum {
 
 void pa_datum_free(pa_datum *d);
 
-/* This will append a suffix to the filename */
-pa_database* pa_database_open(const char *fn, bool for_write);
+/* Database implementation; returns non-empty system architecture name string if database file format depends on system architecture, or NULL otherwise. */
+const char* pa_database_get_arch_suffix(void);
+/* Database implementation; returns non-empty database filename extension string */
+const char* pa_database_get_filename_suffix(void);
+
+/* This will attempt opening database file matching compiled CANONICAL_HOST identifier.
+ * If prependmid is true, file name is augmented with machine id prefix. */
+pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write);
+
+/* Database implementation; opens specified database file using provided path. */
+pa_database* pa_database_open_internal(const char *path, bool for_write);
 void pa_database_close(pa_database *db);
 
 pa_datum* pa_database_get(pa_database *db, const pa_datum *key, pa_datum* data);
index e8ce293..608273a 100644 (file)
@@ -14,6 +14,7 @@ libpulsecore_sources = [
   'cpu-orc.c',
   'cpu-x86.c',
   'device-port.c',
+  'database.c',
   'ffmpeg/resample2.c',
   'filter/biquad.c',
   'filter/crossover.c',