[tracker/tracker-store-ipc: 5/5] Added libtracker-socket-ipc
- From: Philip Van Hoof <pvanhoof src gnome org>
- To: svn-commits-list gnome org
- Subject: [tracker/tracker-store-ipc: 5/5] Added libtracker-socket-ipc
- Date: Sun, 31 May 2009 14:37:31 -0400 (EDT)
commit 1ccde0fb45c7c8c5e1a48ae79fd321db03de469d
Author: Philip Van Hoof <philip codeminded be>
Date: Sun May 31 20:36:41 2009 +0200
Added libtracker-socket-ipc
This is an experimental API for clients to perform rapid SPARQL UPDATE calls
---
configure.ac | 31 +++
src/Makefile.am | 8 +-
src/libtracker-socket-ipc/Makefile.am | 41 ++++
.../tracker-socket-ipc-test.c | 61 ++++++
src/libtracker-socket-ipc/tracker-socket-ipc.c | 225 ++++++++++++++++++++
src/libtracker-socket-ipc/tracker-socket-ipc.h | 43 ++++
src/tracker-store/tracker-socket-listener.c | 12 +-
7 files changed, 416 insertions(+), 5 deletions(-)
diff --git a/configure.ac b/configure.ac
index 81d998c..63b9230 100644
--- a/configure.ac
+++ b/configure.ac
@@ -725,6 +725,36 @@ fi
AM_CONDITIONAL(HAVE_LIBTRACKERGTK, test "$have_libtrackergtk" = "yes")
##################################################################
+# Enable building libtracker-socket-ipc?
+##################################################################
+
+AC_ARG_ENABLE([libtrackersocketipc],
+ AS_HELP_STRING([--enable-libtrackersocketipc],
+ [enable libtrackersocketipc [[default=auto]]]),,
+ [enable_libtrackersocketipc=auto])
+
+if test "x$enable_libtrackersocketipc" != "xno" ; then
+ PKG_CHECK_MODULES(LIBTRACKERSOCKETIPC, [
+ glib-2.0 >= $GLIB_REQUIRED
+ gvariant],
+ [have_libtrackersocketipc=yes],
+ [have_libtrackersocketipc=no])
+
+ AC_SUBST([LIBTRACKERSOCKETIPC_CFLAGS])
+ AC_SUBST([LIBTRACKERSOCKETIPC_LIBS])
+else
+ have_libtrackersocketipc="no (disabled)"
+fi
+
+if test "x$enable_libtrackersocketipc" = "xyes"; then
+ if test "x$have_libtrackersocketipc" != "xyes"; then
+ AC_MSG_ERROR([Couldn't find libtracker_socket_ipc dependencies (glib-2.0 >= $GLIB_REQUIRED, gvariant).])
+ fi
+fi
+
+AM_CONDITIONAL(HAVE_LIBTRACKERSOCKETIPC, test "$have_libtrackersocketipc" = "yes")
+
+##################################################################
# Enable building tracker-applet notification icon?
##################################################################
@@ -1358,6 +1388,7 @@ AC_CONFIG_FILES([
src/libtracker-data/Makefile
src/libtracker-db/Makefile
src/libtracker-gtk/Makefile
+ src/libtracker-socket-ipc/Makefile
src/libtracker/Makefile
src/Makefile
src/rasqal/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 79678cc..9865bc3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,6 +20,10 @@ if HAVE_TRACKER_SEARCH_TOOL
build_tracker_search_tool = tracker-search-tool
endif
+if HAVE_LIBTRACKERSOCKETIPC
+build_libtracker_socket_ipc = libtracker-socket-ipc
+endif
+
SUBDIRS = \
libstemmer \
$(build_libinotify) \
@@ -37,7 +41,8 @@ SUBDIRS = \
$(build_libtrackergtk) \
$(build_tracker_applet) \
$(build_tracker_search_tool) \
- $(build_tracker_preferences)
+ $(build_tracker_preferences) \
+ $(build_libtracker_socket_ipc)
DIST_SUBDIRS = \
libstemmer \
@@ -56,4 +61,5 @@ DIST_SUBDIRS = \
tracker-applet \
tracker-search-tool \
tracker-preferences \
+ libtracker-socket-ipc \
plugins
diff --git a/src/libtracker-socket-ipc/Makefile.am b/src/libtracker-socket-ipc/Makefile.am
new file mode 100644
index 0000000..883a0ba
--- /dev/null
+++ b/src/libtracker-socket-ipc/Makefile.am
@@ -0,0 +1,41 @@
+include $(top_srcdir)/Makefile.decl
+
+INCLUDES = \
+ -DSHAREDIR=\""$(datadir)"\" \
+ -DG_LOG_DOMAIN=\"Tracker\" \
+ -DTRACKER_COMPILATION \
+ -I$(top_srcdir)/src \
+ $(WARN_CFLAGS) \
+ $(GLIB2_CFLAGS) \
+ $(GOBJECT_CFLAGS) \
+ $(GCOV_CFLAGS) \
+ $(LIBTRACKERSOCKETIPC_CFLAGS) \
+ $(UNAC_CFLAGS)
+
+noinst_PROGRAMS = tracker-socket-ipc-test
+
+libtracker_socket_ipcdir = $(libdir)/tracker-$(TRACKER_API_VERSION)
+libtracker_socket_ipcincludedir=$(includedir)/tracker-$(TRACKER_API_VERSION)/libtracker-socket-ipc/
+libtracker_socket_ipc_LTLIBRARIES = libtracker-socket-ipc.la
+
+libtracker_socket_ipc_la_SOURCES = \
+ tracker-socket-ipc.c
+
+libtracker_socket_ipcinclude_HEADERS = \
+ tracker-socket-ipc.h
+
+libtracker_socket_ipc_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+
+libtracker_socket_ipc_la_LIBADD = \
+ $(UNAC_LIBS) \
+ $(GCOV_LIBS) \
+ $(GLIB2_LIBS) \
+ $(LIBTRACKERSOCKETIPC_LIBS)
+
+tracker_socket_ipc_test_SOURCES = tracker-socket-ipc-test.c
+
+tracker_socket_ipc_test_LDADD = $(LIBTRACKERSOCKETIPC_LIBS) \
+ $(GLIB2_LIBS) $(GOBJECT_LIBS) \
+ $(top_builddir)/src/libtracker-socket-ipc/libtracker-socket-ipc.la
+
diff --git a/src/libtracker-socket-ipc/tracker-socket-ipc-test.c b/src/libtracker-socket-ipc/tracker-socket-ipc-test.c
new file mode 100644
index 0000000..ff0abd7
--- /dev/null
+++ b/src/libtracker-socket-ipc/tracker-socket-ipc-test.c
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Philip Van Hoof <philip codeminded be>
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Philip Van Hoof <philip codeminded be>
+ */
+
+#include <glib.h>
+
+#include "tracker-socket-ipc.h"
+
+static void
+on_received (GError *error, gpointer user_data)
+{
+ guint i = (guint) user_data;
+
+ g_print ("Received %u (%s)\n", i,
+ error ? error->message : "OK");
+}
+
+static gboolean
+run_program (gpointer user_data)
+{
+ guint i;
+
+ for (i = 0; i < 1000; i++) {
+ tracker_socket_ipc_queue_sparql_update ("INSERT { <test> a nfo:Document }",
+ on_received, (gpointer) i, NULL);
+ }
+
+ return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+ GMainLoop *loop;
+
+ g_type_init ();
+ tracker_socket_ipc_init ();
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ g_timeout_add_seconds (1, run_program, NULL);
+
+ g_main_loop_run (loop);
+}
diff --git a/src/libtracker-socket-ipc/tracker-socket-ipc.c b/src/libtracker-socket-ipc/tracker-socket-ipc.c
new file mode 100644
index 0000000..825306a
--- /dev/null
+++ b/src/libtracker-socket-ipc/tracker-socket-ipc.c
@@ -0,0 +1,225 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Philip Van Hoof <philip codeminded be>
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Philip Van Hoof <philip codeminded be>
+ */
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+
+#include "tracker-socket-ipc.h"
+
+#define IPC_ERROR_DOMAIN "TrackerSocketIpcDomain"
+#define IPC_DOMAIN g_quark_from_static_string (IPC_ERROR_DOMAIN)
+
+static int sockfd = -1;
+static GHashTable *queued = NULL;
+static gchar standard_buffer[4028];
+
+typedef struct {
+ TrackerSocketIpcSparqlUpdateCallback callback;
+ GDestroyNotify destroy;
+ gpointer user_data;
+} QueuedTask;
+
+static void
+queued_task_free (QueuedTask *queued_task)
+{
+ if (queued_task->destroy) {
+ queued_task->destroy (queued_task->user_data);
+ }
+ g_slice_free (QueuedTask, queued_task);
+}
+
+static gboolean
+data_to_handle_received (GIOChannel *source,
+ GIOCondition cond,
+ gpointer data)
+{
+ gint clientfd = (int) data;
+
+ if (cond & G_IO_IN) {
+ gchar status[40];
+ gsize len;
+
+ len = recv (clientfd, status, sizeof (status), 0);
+
+ if (len == sizeof (status) && status[14] == '{' && status[25] == '}' &&
+ status[27] == '{' && status[38] == '}') {
+
+ QueuedTask *queued_task;
+ gchar *ptr = status + 15;
+ const gchar *key = status + 3;
+ guint data_length;
+ gchar *free_data = NULL, *error_msg;
+ guint error_code;
+
+ status[2] = '\0';
+ status[25] = '\0';
+ status[38] = '\0';
+ status[13] = '\0';
+
+ error_code = atol (ptr);
+
+ ptr = status + 28;
+ data_length = atol (ptr);
+
+ if (data_length > sizeof (standard_buffer)) {
+ free_data = error_msg = (gchar *) malloc (data_length);
+ } else {
+ standard_buffer[data_length] = '\0';
+ error_msg = standard_buffer;
+ }
+
+ len = recv (clientfd, error_msg, data_length, 0);
+
+ queued_task = g_hash_table_lookup (queued, key);
+
+ if (queued_task && len == data_length) {
+ GError *new_error = NULL;
+
+ if (g_strcmp0 (status, "ER") == 0) {
+ g_set_error (&new_error,
+ IPC_DOMAIN,
+ error_code,
+ "%s", error_msg);
+ }
+
+ if (queued_task->callback) {
+ queued_task->callback (new_error,
+ queued_task->user_data);
+ }
+
+ g_hash_table_remove (queued, key);
+
+ g_free (free_data);
+ } else {
+ g_free (free_data);
+ goto failed;
+ }
+
+ } else {
+ goto failed;
+ }
+ }
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ g_io_channel_close (source);
+ goto failed;
+ }
+
+ return TRUE;
+
+failed:
+
+ return FALSE;
+
+}
+
+void
+tracker_socket_ipc_init (void)
+{
+ GIOChannel *io;
+ gchar *path, *tmp;
+ struct sockaddr_un addr;
+ int len;
+
+ tmp = g_strdup_printf ("tracker-%s", g_get_user_name ());
+ path = g_build_filename (g_get_tmp_dir (), tmp, "socket", NULL);
+
+ addr.sun_family = AF_UNIX;
+ strcpy (addr.sun_path, path);
+
+ g_free (tmp);
+ g_free (path);
+
+ sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (!sockfd) {
+ perror ("socket");
+ }
+
+ len = strlen(addr.sun_path) + sizeof(addr.sun_family);
+
+ if (connect(sockfd, (struct sockaddr *)&addr, len) == -1) {
+ perror("connect");
+ close (sockfd);
+ } else {
+
+ //listen (sockfd, 1);
+
+ io = g_io_channel_unix_new (sockfd);
+ signal(SIGPIPE, SIG_IGN);
+
+ queued = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) queued_task_free);
+
+ g_io_add_watch (io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ data_to_handle_received, (gpointer) sockfd);
+
+ g_io_channel_unref (io);
+ }
+}
+
+void
+tracker_socket_ipc_shutdown (void)
+{
+ close (sockfd);
+ g_hash_table_unref (queued);
+}
+
+void
+tracker_socket_ipc_queue_sparql_update (const gchar *sparql,
+ TrackerSocketIpcSparqlUpdateCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ static guint key_counter = 0;
+ QueuedTask *queued_task;
+ gchar *query, *key;
+
+ g_return_if_fail (queued != NULL);
+
+ queued_task = g_slice_new (QueuedTask);
+ queued_task->callback = callback;
+ queued_task->destroy = destroy;
+ queued_task->user_data = user_data;
+
+ key = g_strdup_printf ("%010u", key_counter++);
+
+ query = g_strdup_printf ("UPDATE {%s} {%010u}\n%s",
+ key,
+ strlen (sparql),
+ sparql);
+
+ if (send (sockfd, query, strlen (query), 0) == -1) {
+ perror("send");
+ }
+
+ g_hash_table_insert (queued, key, queued_task);
+
+ g_free (query);
+}
+
diff --git a/src/libtracker-socket-ipc/tracker-socket-ipc.h b/src/libtracker-socket-ipc/tracker-socket-ipc.h
new file mode 100644
index 0000000..5a14bb7
--- /dev/null
+++ b/src/libtracker-socket-ipc/tracker-socket-ipc.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Philip Van Hoof <philip codeminded be>
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Philip Van Hoof <philip codeminded be>
+ */
+
+#ifndef __LIBTRACKER_SOCKET_IPC_H__
+#define __LIBTRACKER_SOCKET_IPC_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef void (* TrackerSocketIpcSparqlUpdateCallback) (GError *error,
+ gpointer user_data);
+
+void tracker_socket_ipc_init (void);
+void tracker_socket_ipc_shutdown (void);
+
+void tracker_socket_ipc_queue_sparql_update (const gchar *sparql,
+ TrackerSocketIpcSparqlUpdateCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy);
+
+G_END_DECLS
+
+#endif /* __LIBTRACKER_SOCKET_IPC_H__ */
diff --git a/src/tracker-store/tracker-socket-listener.c b/src/tracker-store/tracker-socket-listener.c
index ac783ae..4c704b0 100644
--- a/src/tracker-store/tracker-socket-listener.c
+++ b/src/tracker-store/tracker-socket-listener.c
@@ -77,9 +77,13 @@ on_update_fin (GError *error,
}
if (error) {
- message = g_strdup_printf ("ER:%s:%s", info->key, error->message);
+ message = g_strdup_printf ("ER:%s:{%010u}:{%010u}:%s", info->key,
+ error->code,
+ strlen (error->message),
+ error->message);
} else {
- message = g_strdup_printf ("OK:%s", info->key);
+ message = g_strdup_printf ("OK:%s:{%010u}:{%010u}:none", info->key,
+ 0, 4);
}
send (info->clientfd, message, strlen (message), 0);
@@ -102,8 +106,8 @@ data_to_handle_received (GIOChannel *source,
if (len == sizeof (command) && command[7] == '{' && command[18] == '}' &&
command[20] == '{' && command[31] == '}') {
- gchar *ptr = command + 8;
- const gchar *key = command + 21;
+ gchar *ptr = command + 21;
+ const gchar *key = command + 8;
guint data_length;
gchar *free_data = NULL, *query_data;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]