Skip to content

Commit

Permalink
[libgrilio] Added for grilio_channel_lookup(). JB#33787
Browse files Browse the repository at this point in the history
Provides dynamic lookup for named channels.
  • Loading branch information
monich committed Jun 11, 2020
1 parent 58383c5 commit 80f36f8
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 8 deletions.
8 changes: 6 additions & 2 deletions include/grilio_channel.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2020 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
Expand Down Expand Up @@ -137,6 +137,10 @@ grilio_channel_set_name(
GRilIoChannel* channel,
const char* name);

GRilIoChannel*
grilio_channel_lookup(
const char* name); /* Since 1.0.39 */

guint
grilio_channel_serialize(
GRilIoChannel* channel);
Expand Down
62 changes: 61 additions & 1 deletion src/grilio_channel.c
Expand Up @@ -139,6 +139,7 @@ enum grilio_channel_signal {
#define SIGNAL_UNSOL_EVENT_DETAIL_MAX_LENGTH (8)

static guint grilio_channel_signals[SIGNAL_COUNT] = { 0 };
static GHashTable* grilio_channel_table = NULL;

#define NEW_SIGNAL_NO_ARGS(type,X) \
grilio_channel_signals[SIGNAL_##X] = g_signal_new(SIGNAL_##X##_NAME, \
Expand Down Expand Up @@ -190,6 +191,24 @@ grilio_channel_schedule_write(
* Implementation
*==========================================================================*/

static
void
grilio_channel_destroyed(
gpointer key,
GObject* channel)
{
GASSERT(grilio_channel_table);
GDEBUG("Channel \"%s\" has been destroyed", (char*) key);
if (grilio_channel_table) {
GASSERT(g_hash_table_lookup(grilio_channel_table, key) == channel);
g_hash_table_remove(grilio_channel_table, key);
if (g_hash_table_size(grilio_channel_table) == 0) {
g_hash_table_unref(grilio_channel_table);
grilio_channel_table = NULL;
}
}
}

static
gboolean
grilio_channel_generic_id_timeout(
Expand Down Expand Up @@ -1413,14 +1432,55 @@ grilio_channel_set_name(
GRilIoChannel* self,
const char* name)
{
if (G_LIKELY(self)) {
if (G_LIKELY(self) && g_strcmp0(name, self->name)) {
GRilIoChannelPriv* priv = self->priv;

/* Remove old and conflicting entries, if there are any */
if (grilio_channel_table) {
gpointer key, value;

if (self->name && g_hash_table_lookup_extended(grilio_channel_table,
self->name, &key, &value) && value == self) {
/* Our previous entry */
g_object_weak_unref(value, grilio_channel_destroyed, key);
g_hash_table_remove(grilio_channel_table, key);
}
if (name && g_hash_table_lookup_extended(grilio_channel_table,
name, &key, &value)) {
/* Conflicting entry */
g_object_weak_unref(value, grilio_channel_destroyed, key);
g_hash_table_remove(grilio_channel_table, key);
}
}

/* Actually update the name */
grilio_transport_set_name(priv->transport, name);
self->name = priv->transport->name;

/* Store weak reference in the global table */
if (name) {
gpointer key = g_strdup(name);

if (!grilio_channel_table) {
grilio_channel_table = g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, NULL);
}
g_hash_table_insert(grilio_channel_table, key, self);
g_object_weak_ref(G_OBJECT(self), grilio_channel_destroyed, key);
}
}
}

GRilIoChannel*
grilio_channel_lookup(
const char* name) /* Since 1.0.39 */
{
if (G_LIKELY(name) && grilio_channel_table) {
return g_hash_table_lookup(grilio_channel_table, name);
}
return NULL;
}

guint
grilio_channel_serialize(
GRilIoChannel* self)
Expand Down
36 changes: 31 additions & 5 deletions test/test_io/test_io.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2020 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
Expand Down Expand Up @@ -156,7 +156,6 @@ test_alloc(
test->server = server;
test->transport = grilio_transport_socket_new(fd, "SUB1", FALSE);
test->io = grilio_channel_new(test->transport);
grilio_channel_set_name(test->io, "TEST");
test->log = grilio_channel_add_default_logger(test->io, GLOG_LEVEL_VERBOSE);
if (!(test_opt.flags & TEST_FLAG_DEBUG)) {
test->timeout_id = g_timeout_add_seconds(TEST_TIMEOUT,
Expand Down Expand Up @@ -444,13 +443,40 @@ test_basic(
GRilIoRequest* req = grilio_request_new();
guint id, pending_event_count = 0;
guint32 invalid[3];
const char* name = "TEST";
const char* name1 = "TEST1";
gulong pending_id = grilio_channel_add_pending_changed_handler(test->io,
test_basic_inc, &pending_event_count);

grilio_channel_set_name(test->io, "");
g_assert(!g_strcmp0(test->io->name, ""));
GRilIoTestServer* tmp_server = grilio_test_server_new(TRUE);
GRilIoTransport* tmp_trans = grilio_transport_socket_new
(grilio_test_server_fd(tmp_server), NULL, FALSE);
GRilIoChannel* tmp_io = grilio_channel_new(tmp_trans);

/* Test naming and global channel registry */
g_assert(!grilio_channel_lookup(NULL));
g_assert(!grilio_channel_lookup(name)); /* It's not there */
grilio_channel_set_name(test->io, name); /* Overwrite the previous one */
grilio_channel_set_name(test->io, name); /* Second time does nothing */
g_assert(!g_strcmp0(test->io->name, name));
g_assert(grilio_channel_lookup(name) == test->io); /* Now it's there */
grilio_channel_set_name(test->io, NULL);
g_assert(!test->io->name);
g_assert(!grilio_channel_lookup(name)); /* It's not there anymore */
grilio_channel_set_name(test->io, name); /* Set it again */
g_assert(grilio_channel_lookup(name) == test->io); /* It's there again */
grilio_channel_set_name(tmp_io, name); /* Overwrite it */
g_assert(grilio_channel_lookup(name) == tmp_io); /* Overwritten */
grilio_channel_set_name(test->io, NULL); /* Clear this name */
g_assert(grilio_channel_lookup(name) == tmp_io); /* This one still there */
grilio_channel_set_name(test->io, name);
grilio_channel_set_name(tmp_io, name1); /* Set different name for it */

grilio_channel_unref(tmp_io);
grilio_transport_unref(tmp_trans);
grilio_test_server_free(tmp_server);
g_assert(!grilio_channel_lookup(name1)); /* Gone */
g_assert(grilio_channel_lookup(name) == test->io); /* Still there */

/* Test NULL resistance */
g_assert(!grilio_request_retry_count(NULL));
Expand Down

0 comments on commit 80f36f8

Please sign in to comment.