[tracker/tracker-store-ipc] Unix socket experiment



commit d7c6ca7529a8fe9bf63f8af728a92f3df1c06d7b
Author: Philip Van Hoof <philip codeminded be>
Date:   Thu May 28 20:41:42 2009 +0200

    Unix socket experiment
---
 src/tracker-store/Makefile.am               |    4 +-
 src/tracker-store/tracker-main.c            |    4 +
 src/tracker-store/tracker-socket-listener.c |  197 +++++++++++++++++++++++++++
 src/tracker-store/tracker-socket-listener.h |   29 ++++
 tests/estress/socket_stress_test.c          |   67 +++++++++
 5 files changed, 300 insertions(+), 1 deletions(-)

diff --git a/src/tracker-store/Makefile.am b/src/tracker-store/Makefile.am
index 10e2c7a..f087beb 100644
--- a/src/tracker-store/Makefile.am
+++ b/src/tracker-store/Makefile.am
@@ -53,7 +53,9 @@ tracker_store_SOURCES =							\
 	tracker-resource-class.c					\
 	tracker-resource-class.h					\
 	tracker-store.c							\
-	tracker-store.h
+	tracker-store.h							\
+	tracker-socket-listener.c					\
+	tracker-socket-listener.h
 
 if OS_WIN32
 tracker_store_win_libs = -lws2_32 -lkernel32
diff --git a/src/tracker-store/tracker-main.c b/src/tracker-store/tracker-main.c
index 5c23125..52ee020 100644
--- a/src/tracker-store/tracker-main.c
+++ b/src/tracker-store/tracker-main.c
@@ -73,6 +73,7 @@
 #include "tracker-backup.h"
 #include "tracker-daemon.h"
 #include "tracker-store.h"
+#include "tracker-socket-listener.h"
 
 #ifdef G_OS_WIN32
 #include <windows.h>
@@ -967,6 +968,7 @@ main (gint argc, gchar *argv[])
 
 	tracker_events_init (tracker_daemon_get_notifiable_classes);
 	tracker_push_init (config);
+	tracker_socket_listener_init ();
 
 	g_message ("Waiting for DBus requests...");
 
@@ -996,6 +998,8 @@ main (gint argc, gchar *argv[])
 
 	g_message ("Cleaning up");
 
+	tracker_socket_listener_shutdown ();
+
 	shutdown_databases ();
 	shutdown_directories ();
 
diff --git a/src/tracker-store/tracker-socket-listener.c b/src/tracker-store/tracker-socket-listener.c
new file mode 100644
index 0000000..f8ea1fe
--- /dev/null
+++ b/src/tracker-store/tracker-socket-listener.c
@@ -0,0 +1,197 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009, Nokia
+ *
+ * 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.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+/* Some of this code might accidentally look a bit like BlueZ's unix.c file, any
+ * resemblance is purely intentional ;-). Thanks for the code Marcel Holtmann */
+
+#include <glib.h>
+
+#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-listener.h"
+#include "tracker-store.h"
+
+static int sockfd = -1;
+static gchar standard_buffer[4028];
+
+static gboolean
+data_to_handle_received (GIOChannel *source,
+                         GIOCondition cond,
+                         gpointer data)
+{
+	if (cond & G_IO_IN) {
+		gchar command[20];
+		gsize len;
+		gint clientfd;
+
+		clientfd = g_io_channel_unix_get_fd (source);
+		len = recv (clientfd, command, sizeof (command), 0);
+
+		if (len == sizeof (command) && command[7] == '{' && command[18] == '}') {
+			gchar *ptr = command + 8;
+			guint data_length;
+			gchar *free_data = NULL, *query_data;
+
+			command[18] = '\0';
+			data_length = atol (ptr);
+
+			if (data_length > sizeof (standard_buffer)) {
+				free_data = query_data = (gchar *) malloc (data_length);
+			} else {
+				standard_buffer[data_length] = '\0';
+				query_data = standard_buffer;
+			}
+
+			len = recv (clientfd, query_data, data_length, 0);
+
+			if (len == data_length) {
+				if (strstr (command, "UPDATE")) {
+
+					/* g_debug ("QUEUED: %s\n", query_data); */
+					tracker_store_queue_sparql_update (query_data, 
+					                                   NULL, NULL, NULL);
+
+				} else {
+					goto failed;
+				}
+
+				g_free (free_data);
+			} else {
+				g_free (free_data);
+				goto failed;
+			}
+
+		} else {
+			goto failed;
+		}
+	}
+
+	if (cond & (G_IO_HUP | G_IO_ERR)) {
+		goto failed;
+	}
+
+	return TRUE;
+
+failed:
+
+	return FALSE;
+
+}
+
+static gboolean server_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+	struct sockaddr_un addr;
+	socklen_t addrlen;
+	int sk, cli_sk;
+	GIOChannel *io;
+
+	if (cond & G_IO_NVAL)
+		return FALSE;
+
+	if (cond & (G_IO_HUP | G_IO_ERR)) {
+		g_io_channel_close (chan);
+		return FALSE;
+	}
+
+	sk = g_io_channel_unix_get_fd (chan);
+	memset(&addr, 0, sizeof (addr));
+	addrlen = sizeof (addr);
+	cli_sk = accept(sk, (struct sockaddr *) &addr, &addrlen);
+
+	if (cli_sk < 0) {
+		return TRUE;
+	}
+
+	io = g_io_channel_unix_new(cli_sk);
+	g_io_add_watch (io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+	                data_to_handle_received, NULL);
+	g_io_channel_unref(io);
+
+	return TRUE;
+}
+
+static int 
+set_nonblocking(int fd)
+{
+	long arg;
+	arg = fcntl(fd, F_GETFL);
+	if (arg < 0)
+		return -errno;
+	if (arg & O_NONBLOCK)
+		return 0;
+	arg |= O_NONBLOCK;
+	if (fcntl(fd, F_SETFL, arg) < 0)
+		return -errno;
+	return 0;
+}
+
+void
+tracker_socket_listener_init (void)
+{
+	GIOChannel *io;
+	gchar *path, *tmp;
+	struct sockaddr_un addr;
+
+	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_unlink (path);
+
+	g_free (tmp);
+	g_free (path);
+
+	sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+	if (!sockfd) {
+		perror ("socket");
+	}
+
+	if (bind (sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror ("bind");
+		close(sockfd);
+	} else {
+
+		set_nonblocking (sockfd);
+
+		listen (sockfd, 1);
+
+		io = g_io_channel_unix_new (sockfd);
+		g_io_add_watch (io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+		                server_cb, NULL);
+	
+		g_io_channel_unref (io);
+	}
+}
+
+void
+tracker_socket_listener_shutdown (void)
+{
+	close (sockfd);
+}
diff --git a/src/tracker-store/tracker-socket-listener.h b/src/tracker-store/tracker-socket-listener.h
new file mode 100644
index 0000000..a206b00
--- /dev/null
+++ b/src/tracker-store/tracker-socket-listener.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009, Nokia
+ *
+ * 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.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+#ifndef __TRACKER_SOCKET_LISTENER_H__
+#define __TRACKER_SOCKET_LISTENER_H__
+
+void tracker_socket_listener_init (void);
+void tracker_socket_listener_shutdown (void);
+
+#endif
\ No newline at end of file
diff --git a/tests/estress/socket_stress_test.c b/tests/estress/socket_stress_test.c
new file mode 100755
index 0000000..c805fbd
--- /dev/null
+++ b/tests/estress/socket_stress_test.c
@@ -0,0 +1,67 @@
+#include <glib.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+    
+
+int main(void)
+{
+        int s, t, len;
+        struct sockaddr_un remote;
+	const char *str;
+	int i = 0;
+	gchar *path, *tmp;
+	struct sockaddr_un addr;
+	GTimer *timer;
+
+        if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+            perror("socket");
+            exit(1);
+        }
+
+        printf("Trying to connect...\n");
+
+	tmp = g_strdup_printf ("tracker-%s", g_get_user_name ());
+	path = g_build_filename (g_get_tmp_dir (), tmp, "socket", NULL);
+
+	remote.sun_family = AF_UNIX;
+	strcpy (remote.sun_path, path);
+
+	g_free (tmp);
+	g_free (path);
+
+        len = strlen(remote.sun_path) + sizeof(remote.sun_family);
+        if (connect(s, (struct sockaddr *)&remote, len) == -1) {
+            perror("connect");
+            exit(1);
+        }
+
+        printf("Connected.\n");
+
+	str = "UPDATE {0000000032}\nINSERT { <test> a nfo:Document }";
+
+	timer = g_timer_new ();
+
+	g_timer_start (timer);
+	for (i = 0; i < 10000; i++) {
+            if (send(s, str, strlen(str), 0) == -1) {
+                perror("send");
+                exit(1);
+            }
+        }
+	g_timer_stop (timer);
+
+	printf ("%f\n", g_timer_elapsed (timer, NULL));
+
+	g_timer_destroy (timer);
+
+        close(s);
+
+        return 0;
+}
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]