[gnome-photos/sam/tracker3: 16/27] Bundle Tracker 3 in the Flatpak for systems which don't have it
- From: Sam Thursfield <sthursfield src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos/sam/tracker3: 16/27] Bundle Tracker 3 in the Flatpak for systems which don't have it
- Date: Thu, 13 Aug 2020 00:11:03 +0000 (UTC)
commit 8c94e24a756e5e25767bb137a29c6debef31b55e
Author: Sam Thursfield <sam afuera me uk>
Date: Fri Jul 10 01:14:05 2020 +0200
Bundle Tracker 3 in the Flatpak for systems which don't have it
This commit allows the tracker3 version of GNOME Photos to run on systems
which don't have a suitable version of Tracker in the base OS. It does
this by running tracker-miner-fs-3 inside the Flatpak sandbox. This will
lead to increased resource consumption as it'll duplicate the work of
any indexer in the host OS, but it's better than a broken app.
Based on work by Yi-Soo An <yisooan gmail com>
in https://gitlab.gnome.org/GNOME/gnome-photos/-/merge_requests/67
data/meson.build | 2 +
data/tracker/meson.build | 33 +++++
....gnome.Photos.Tracker3.Miner.Extract.service.in | 7 +
...rg.gnome.Photos.Tracker3.Miner.Files.service.in | 7 +
data/tracker/org.gnome.Photos.domain.rule.in | 20 +++
flatpak/org.gnome.Photos.json | 20 +--
src/photos-application.c | 3 +-
src/photos-query-builder.c | 10 ++
src/photos-search-context.c | 3 +
src/photos-search-context.h | 1 +
src/photos-tracker-queue.c | 151 ++++++++++++++++++++-
src/photos-tracker-queue.h | 2 +
src/queries/all.sparql.template | 2 +-
src/queries/favorite-photos.sparql.template | 2 +-
src/queries/photos.sparql.template | 2 +-
15 files changed, 242 insertions(+), 23 deletions(-)
---
diff --git a/data/meson.build b/data/meson.build
index 7898b0cc..f0d85d4b 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -54,3 +54,5 @@ install_data(
photos_namespace.to_lower() + '.gschema.xml',
install_dir: join_paths(photos_datadir, 'glib-2.0', 'schemas'),
)
+
+subdir('tracker')
diff --git a/data/tracker/meson.build b/data/tracker/meson.build
new file mode 100644
index 00000000..accc99c2
--- /dev/null
+++ b/data/tracker/meson.build
@@ -0,0 +1,33 @@
+# Files needed for running Tracker inside the Flatpak sandbox, for systems
+# which don't have a suitable version of Tracker in the host OS.
+#
+# We must export the .service files from the sandbox so they work on the
+# session bus. This means the Tracker domain name must correspond with the
+# application ID.
+
+
+domain_ontologies_dir = get_option('datadir') / 'tracker3' / 'domain-ontologies'
+dbus_services_dir = get_option('datadir') / 'dbus-1' / 'services'
+
+tracker_domain_config = configuration_data()
+tracker_domain_config.set('application_id', photos_namespace)
+tracker_domain_config.set('domain_rule', get_option('prefix') / domain_ontologies_dir / photos_namespace +
'.domain.rule')
+
+configure_file(
+ input: 'org.gnome.Photos.domain.rule.in',
+ output: photos_namespace + '.domain.rule',
+ configuration: tracker_domain_config,
+ install_dir: domain_ontologies_dir)
+
+configure_file(
+ input: 'org.gnome.Photos.Tracker3.Miner.Extract.service.in',
+ output: photos_namespace + '.Tracker3.Miner.Extract.service',
+ configuration: tracker_domain_config,
+ install_dir: dbus_services_dir)
+
+configure_file(
+ input: 'org.gnome.Photos.Tracker3.Miner.Files.service.in',
+ output: photos_namespace + '.Tracker3.Miner.Files.service',
+ configuration: tracker_domain_config,
+ install_dir: dbus_services_dir)
+
diff --git a/data/tracker/org.gnome.Photos.Tracker3.Miner.Extract.service.in
b/data/tracker/org.gnome.Photos.Tracker3.Miner.Extract.service.in
new file mode 100644
index 00000000..eb7a87aa
--- /dev/null
+++ b/data/tracker/org.gnome.Photos.Tracker3.Miner.Extract.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Extract
+Exec=/app/libexec/tracker-extract-3 --domain-ontology @domain_rule@
+
+# Miner details needed for tracker-control
+Path=/org/freedesktop/Tracker3/Miner/Extract
+NameSuffix=Miner.Files
diff --git a/data/tracker/org.gnome.Photos.Tracker3.Miner.Files.service.in
b/data/tracker/org.gnome.Photos.Tracker3.Miner.Files.service.in
new file mode 100644
index 00000000..4fa7371d
--- /dev/null
+++ b/data/tracker/org.gnome.Photos.Tracker3.Miner.Files.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Files
+Exec=/app/libexec/tracker-miner-fs-3 --domain-ontology @domain_rule@ --initial-sleep 0
+
+# Miner details needed for tracker-control
+Path=/org/freedesktop/Tracker3/Miner/Files
+NameSuffix=Miner.Files
diff --git a/data/tracker/org.gnome.Photos.domain.rule.in b/data/tracker/org.gnome.Photos.domain.rule.in
new file mode 100644
index 00000000..8f5fc4a1
--- /dev/null
+++ b/data/tracker/org.gnome.Photos.domain.rule.in
@@ -0,0 +1,20 @@
+# This defines a private Tracker domain for GNOME Photos.
+#
+# It's used to run the Tracker indexer inside a Flatpak sandbox, when Photos is
+# running on a host that doesn't have a suitable version of Tracker installed.
+
+[DomainOntology]
+# Location for the Tracker database
+CacheLocation=$XDG_CACHE_HOME/gnome-photos/miner/files
+
+# Name of the ontology to use, must be one located in
+# $(sharedir)/tracker/ontologies
+OntologyName=nepomuk
+
+# DBus name for the owner (not optional). Tracker will use
+# the domain as the prefix of the DBus name for all the
+# services related to this domain ontology.
+Domain=@application_id@
+
+# List of miners we expect to run in this domain.
+Miners=Miner.Files;Miner.Extract
diff --git a/flatpak/org.gnome.Photos.json b/flatpak/org.gnome.Photos.json
index 490fe946..97c4acda 100644
--- a/flatpak/org.gnome.Photos.json
+++ b/flatpak/org.gnome.Photos.json
@@ -10,6 +10,8 @@
"--filesystem=xdg-download",
"--filesystem=xdg-pictures",
"--metadata=X-DConf=migrate-path=/org/gnome/photos/",
+ "--own-name=org.gnome.Photos.Tracker3.Miner.Extract",
+ "--own-name=org.gnome.Photos.Tracker3.Miner.Files",
"--share=ipc",
"--share=network",
"--socket=fallback-x11",
@@ -249,20 +251,10 @@
{
"name": "tracker-miners",
"buildsystem": "meson",
- "cleanup": [ "/etc",
- "/lib",
- "/libexec",
- "/share/dbus-1/services/org.freedesktop.Tracker1.Miner.Extract.service",
- "/share/dbus-1/services/org.freedesktop.Tracker1.Writeback.service",
- "/share/tracker/miners/org.freedesktop.Tracker1.Miner.Applications.service",
- "/share/tracker/miners/org.freedesktop.Tracker1.Miner.Extract.service",
- "/share/tracker/miners/org.freedesktop.Tracker1.Miner.RSS.service",
- "/share/tracker-miners",
- "/share/glib-2.0/schemas/org.freedesktop.Tracker.Extract.gschema.xml",
- "/share/glib-2.0/schemas/org.freedesktop.Tracker.Writeback.gschema.xml" ],
- "config-opts": [ "-Dextract=false",
- "-Dgeneric_media_extractor=none",
- "-Dman=false",
+ "cleanup": [ "/share/dbus-1/services/org.freedesktop.Tracker3.Miner.Extract.service",
+ "/share/dbus-1/services/org.freedesktop.Tracker3.Miner.Files.service",
+ "/share/dbus-1/services/org.freedesktop.Tracker3.Writeback.service" ],
+ "config-opts": [ "-Dman=false",
"-Dminer_fs=true",
"-Dminer_rss=false",
"-Dsystemd_user_services=false",
diff --git a/src/photos-application.c b/src/photos-application.c
index 03448fbb..3b60350f 100644
--- a/src/photos-application.c
+++ b/src/photos-application.c
@@ -3126,8 +3126,7 @@ photos_application_get_miners_running (PhotosApplication *self)
return self->miners_running;
}
-
-gint
+int
photos_application_get_scale_factor (PhotosApplication *self)
{
GList *windows;
diff --git a/src/photos-query-builder.c b/src/photos-query-builder.c
index 085278e0..d029f80e 100644
--- a/src/photos-query-builder.c
+++ b/src/photos-query-builder.c
@@ -25,6 +25,7 @@
#include <string.h>
+#include "photos-application.h"
#include "photos-base-manager.h"
#include "photos-query.h"
#include "photos-query-builder.h"
@@ -32,6 +33,7 @@
#include "photos-source-manager.h"
#include "photos-search-match-manager.h"
#include "photos-search-type-manager.h"
+#include "photos-tracker-queue.h"
#define PHOTOS_QUERY_COLLECTIONS_IDENTIFIER "photos:collection:"
#define PHOTOS_QUERY_LOCAL_COLLECTIONS_IDENTIFIER "photos:collection:local:"
@@ -53,6 +55,7 @@ photos_query_builder_query (PhotosSearchContextState *state,
PhotosOffsetController *offset_cntrlr)
{
PhotosSparqlTemplate *template;
+ const gchar *miner_fs_busname = NULL;
const gchar *outer_projection = NULL;
const gchar *inner_projection = NULL;
g_autofree gchar *item_pattern = NULL;
@@ -64,6 +67,8 @@ photos_query_builder_query (PhotosSearchContextState *state,
template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
+ miner_fs_busname = photos_tracker_queue_get_miner_fs_busname (state->queue);
+
outer_projection = "?urn ?file ?filename ?mimetype ?title ?author_name ?mtime ?identifier ?type
?datasource "
"( EXISTS { ?urn nao:hasTag nao:predefined-tag-favorite } ) AS ?is_favorite"
"?has_contributor ?ctime ?width ?height ?equipment ?orientation ?exposure_time ?fnumber
"
@@ -117,6 +122,7 @@ photos_query_builder_query (PhotosSearchContextState *state,
}
sparql = photos_sparql_template_get_sparql (template,
+ "miner_fs_busname", miner_fs_busname,
"outer_projection", outer_projection,
"inner_projection", inner_projection,
"collections_default_filter", collections_default_filter,
@@ -186,6 +192,7 @@ PhotosQuery *
photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
{
PhotosSparqlTemplate *template;
+ const gchar *miner_fs_busname = NULL;
const gchar *inner_projection = NULL;
const gchar *outer_projection = NULL;
g_autofree gchar *item_pattern = NULL;
@@ -196,6 +203,8 @@ photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
+ miner_fs_busname = photos_tracker_queue_get_miner_fs_busname (state->queue);
+
outer_projection = "?count ";
inner_projection = "COUNT(?urn) AS ?count ";
@@ -208,6 +217,7 @@ photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
}
sparql = photos_sparql_template_get_sparql (template,
+ "miner_fs_busname", miner_fs_busname,
"outer_projection", outer_projection,
"inner_projection", inner_projection,
"collections_default_filter", collections_default_filter,
diff --git a/src/photos-search-context.c b/src/photos-search-context.c
index 4b503798..4840caff 100644
--- a/src/photos-search-context.c
+++ b/src/photos-search-context.c
@@ -31,6 +31,7 @@
#include "photos-search-match-manager.h"
#include "photos-search-type-manager.h"
#include "photos-source-manager.h"
+#include "photos-tracker-queue.h"
G_DEFINE_INTERFACE (PhotosSearchContext, photos_search_context, G_TYPE_OBJECT);
@@ -54,6 +55,7 @@ photos_search_context_state_new (PhotosSearchContext *self)
state->srch_cntrlr = photos_search_controller_new ();
state->srch_mtch_mngr = photos_search_match_manager_new (state->srch_cntrlr);
state->srch_typ_mngr = photos_search_type_manager_new ();
+ state->queue = photos_tracker_queue_dup_singleton (NULL, NULL);
return state;
}
@@ -68,6 +70,7 @@ photos_search_context_state_free (PhotosSearchContextState *state)
g_object_unref (state->srch_mtch_mngr);
g_object_unref (state->srch_typ_mngr);
g_object_unref (state->srch_cntrlr);
+ g_object_unref (state->queue);
g_slice_free (PhotosSearchContextState, state);
}
diff --git a/src/photos-search-context.h b/src/photos-search-context.h
index 2af6cf96..5a18d386 100644
--- a/src/photos-search-context.h
+++ b/src/photos-search-context.h
@@ -41,6 +41,7 @@ struct _PhotosSearchContextState
gpointer srch_typ_mngr;
gpointer offset_cntrlr;
gpointer srch_cntrlr;
+ gpointer queue;
};
PhotosSearchContextState *photos_search_context_state_new (PhotosSearchContext *self);
diff --git a/src/photos-tracker-queue.c b/src/photos-tracker-queue.c
index 99abf29f..cf1b8b96 100644
--- a/src/photos-tracker-queue.c
+++ b/src/photos-tracker-queue.c
@@ -40,6 +40,15 @@ struct _PhotosTrackerQueue
TrackerSparqlConnection *connection;
gboolean is_initialized;
gboolean running;
+ gboolean miner_fs_ready;
+ const gchar *miner_fs_busname;
+};
+
+enum
+{
+ PROP_0,
+ PROP_MINER_FS_READY,
+ PROP_MINER_FS_BUSNAME
};
static void photos_tracker_queue_initable_iface_init (GInitableIface *iface);
@@ -90,7 +99,6 @@ photos_tracker_queue_data_free (PhotosTrackerQueueData *data)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (PhotosTrackerQueueData, photos_tracker_queue_data_free);
-
static PhotosTrackerQueueData *
photos_tracker_queue_data_new (PhotosQuery *query,
PhotosTrackerQueryType query_type,
@@ -208,6 +216,64 @@ photos_tracker_queue_check (PhotosTrackerQueue *self)
}
}
+static const gchar *
+photos_tracker_queue_start_session_miner_fs (PhotosTrackerQueue *self, GError **error)
+{
+ g_autoptr(TrackerSparqlConnection) miner_fs = NULL;
+ const gchar *busname = "org.freedesktop.Tracker3.Miner.Files";
+
+ miner_fs = tracker_sparql_connection_bus_new (busname, NULL, NULL, error);
+ if (*error)
+ {
+ /* Creating the connection should always succeed, so this is weird. */
+ g_warning ("Unable to create connection for session-wide Tracker indexer: %s", (*error)->message);
+ return NULL;
+ }
+
+ return busname;
+}
+
+static const gchar *
+photos_tracker_queue_start_local_miner_fs (PhotosTrackerQueue *self, GError **error)
+{
+ GDBusConnection *bus;
+ const gchar *busname = "org.gnome.Photos.Tracker3.Miner.Files";
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
+
+ if (*error)
+ {
+ g_critical ("Could not connect to session bus: %s", (*error)->message);
+ return NULL;
+ }
+
+ photos_debug (PHOTOS_DEBUG_TRACKER, "Contacting %s", busname);
+ g_dbus_connection_call_sync (bus,
+ busname,
+ "/org/freedesktop/Tracker3/Miner/Files",
+ "org.freedesktop.DBus.Peer",
+ "Ping",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ 5000, /* Startup timeout for miner-fs in msec */
+ NULL,
+ error);
+
+ if (*error)
+ {
+ g_critical ("Could not start local Tracker indexer at %s: %s", busname, (*error)->message);
+ return NULL;
+ }
+
+ return busname;
+}
+
+static gboolean
+inside_flatpak (void)
+{
+ return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
+}
static GObject *
photos_tracker_queue_constructor (GType type, guint n_construct_params, GObjectConstructParam
*construct_params)
@@ -256,6 +322,38 @@ photos_tracker_queue_init (PhotosTrackerQueue *self)
self->queue = g_queue_new ();
}
+static void
+photos_tracker_queue_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ PhotosTrackerQueue *self = PHOTOS_TRACKER_QUEUE (object);
+
+ switch (prop_id)
+ {
+ case PROP_MINER_FS_READY:
+ g_value_set_boolean (value, self->miner_fs_ready);
+ break;
+
+ case PROP_MINER_FS_BUSNAME:
+ g_value_set_string (value, self->miner_fs_busname);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+photos_tracker_queue_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ /* All properties are read only */
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
static void
photos_tracker_queue_class_init (PhotosTrackerQueueClass *class)
@@ -265,6 +363,24 @@ photos_tracker_queue_class_init (PhotosTrackerQueueClass *class)
object_class->constructor = photos_tracker_queue_constructor;
object_class->dispose = photos_tracker_queue_dispose;
object_class->finalize = photos_tracker_queue_finalize;
+ object_class->get_property = photos_tracker_queue_get_property;
+ object_class->set_property = photos_tracker_queue_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_MINER_FS_READY,
+ g_param_spec_boolean ("tracker-miner-fs-ready",
+ "Tracker Miner FS ready",
+ "TRUE if it is possible to query Tracker indexer",
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_MINER_FS_BUSNAME,
+ g_param_spec_string ("tracker-miner-fs-busname",
+ "Tracker Miner FS busname",
+ "D-Bus name of the Tracker indexer daemon",
+ "",
+ G_PARAM_READABLE));
}
@@ -290,7 +406,9 @@ photos_tracker_queue_initable_init (GInitable *initable, GCancellable *cancellab
g_assert_no_error (self->initialization_error);
- /* Same flags that tracker-miner-fs uses by default. See:
+ /* Connect to the local database which stores user data.
+ *
+ * Same flags that tracker-miner-fs uses by default. See:
* https://gitlab.gnome.org/GNOME/tracker-miners/-/blob/master/src/miners/fs/tracker-main.c#L735 and
*
https://gitlab.gnome.org/GNOME/tracker-miners/-/blob/master/data/org.freedesktop.Tracker.FTS.gschema.xml */
tracker_flags = TRACKER_SPARQL_CONNECTION_FLAGS_FTS_ENABLE_UNACCENT |
@@ -299,6 +417,7 @@ photos_tracker_queue_initable_init (GInitable *initable, GCancellable *cancellab
store = g_file_new_build_filename (g_get_user_data_dir (), "gnome-photos", NULL);
+ photos_debug (PHOTOS_DEBUG_TRACKER, "Opening local database at %s", g_file_peek_path (store));
self->connection = tracker_sparql_connection_new (tracker_flags,
store,
tracker_sparql_get_ontology_nepomuk (),
@@ -308,7 +427,26 @@ photos_tracker_queue_initable_init (GInitable *initable, GCancellable *cancellab
if (G_UNLIKELY (self->initialization_error != NULL))
goto out;
- ret_val = TRUE;
+ /* Connect to filesystem indexer. */
+ self->miner_fs_busname = photos_tracker_queue_start_session_miner_fs (self, &self->initialization_error);
+
+ if (!self->miner_fs_busname && inside_flatpak ())
+ {
+ g_clear_error (&self->initialization_error);
+ self->miner_fs_busname = photos_tracker_queue_start_local_miner_fs (self, &self->initialization_error);
+ }
+
+ if (self->miner_fs_busname)
+ {
+ photos_debug (PHOTOS_DEBUG_TRACKER, "Using %s as tracker-miner-fs", self->miner_fs_busname);
+ ret_val = TRUE;
+ }
+ else
+ {
+ photos_debug (PHOTOS_DEBUG_TRACKER, "Initialization failed due to %s",
self->initialization_error->message);
+ ret_val = FALSE;
+ }
+
out:
self->is_initialized = TRUE;
@@ -329,7 +467,6 @@ photos_tracker_queue_initable_iface_init (GInitableIface *iface)
iface->init = photos_tracker_queue_initable_init;
}
-
PhotosTrackerQueue *
photos_tracker_queue_dup_singleton (GCancellable *cancellable, GError **error)
{
@@ -339,6 +476,11 @@ photos_tracker_queue_dup_singleton (GCancellable *cancellable, GError **error)
return g_initable_new (PHOTOS_TYPE_TRACKER_QUEUE, cancellable, error, NULL);
}
+const gchar *
+photos_tracker_queue_get_miner_fs_busname (PhotosTrackerQueue *self)
+{
+ return self->miner_fs_busname;
+}
void
photos_tracker_queue_select (PhotosTrackerQueue *self,
@@ -365,6 +507,7 @@ photos_tracker_queue_select (PhotosTrackerQueue *self,
}
+
void
photos_tracker_queue_update (PhotosTrackerQueue *self,
PhotosQuery *query,
diff --git a/src/photos-tracker-queue.h b/src/photos-tracker-queue.h
index 93d97306..2a7118fc 100644
--- a/src/photos-tracker-queue.h
+++ b/src/photos-tracker-queue.h
@@ -34,6 +34,8 @@ G_DECLARE_FINAL_TYPE (PhotosTrackerQueue, photos_tracker_queue, PHOTOS, TRACKER_
PhotosTrackerQueue *photos_tracker_queue_dup_singleton (GCancellable *cancellable, GError
**error);
+const gchar * photos_tracker_queue_get_miner_fs_busname (PhotosTrackerQueue *self);
+
void photos_tracker_queue_select (PhotosTrackerQueue *self,
PhotosQuery *query,
GCancellable *cancellable,
diff --git a/src/queries/all.sparql.template b/src/queries/all.sparql.template
index 1582a9b3..44ab2d66 100644
--- a/src/queries/all.sparql.template
+++ b/src/queries/all.sparql.template
@@ -19,7 +19,7 @@ FROM NAMED tracker:Pictures
{
SELECT {{inner_projection}}
{
- SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files>
+ SERVICE <dbus:{{miner_fs_busname}}>
{
?urn a nmm:Photo ;
nie:isStoredAs ?file .
diff --git a/src/queries/favorite-photos.sparql.template b/src/queries/favorite-photos.sparql.template
index d0db90ae..31ef27b0 100644
--- a/src/queries/favorite-photos.sparql.template
+++ b/src/queries/favorite-photos.sparql.template
@@ -3,7 +3,7 @@ FROM tracker:Pictures
{
?urn a nmm:Photo .
?urn a nmm:Photo; nao:hasTag nao:predefined-tag-favorite .
- SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files>
+ SERVICE <dbus:{{miner_fs_busname}}>
{
SELECT {{inner_projection}}
{
diff --git a/src/queries/photos.sparql.template b/src/queries/photos.sparql.template
index 843357ca..021609fd 100644
--- a/src/queries/photos.sparql.template
+++ b/src/queries/photos.sparql.template
@@ -1,7 +1,7 @@
SELECT {{outer_projection}}
FROM tracker:Pictures
{
- SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files>
+ SERVICE <dbus:{{miner_fs_busname}}>
{
SELECT {{inner_projection}}
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]