Permalink
Browse files

Merge pull request #12 from mtasaka/localwork

Cancel old monitors only when cache regeneration succeeds.
  • Loading branch information...
LStranger committed Oct 20, 2016
2 parents 2932d67 + 5800ac6 commit 4a65262b77f03e38f85b1b887d37ee274d9f476b
Showing with 53 additions and 16 deletions.
  1. +53 −16 menu-cache-daemon/menu-cached.c
@@ -76,6 +76,11 @@ typedef struct _Cache
char *cache_file;
}Cache;
typedef struct ClientIO_ {
guint source_id;
GIOChannel *channel;
} ClientIO;
static GMainLoop* main_loop = NULL;
static GHashTable* hash = NULL;
@@ -85,6 +90,8 @@ static char *socket_file = NULL;
static void on_file_changed( GFileMonitor* mon, GFile* gf, GFile* other,
GFileMonitorEvent evt, Cache* cache );
static void on_client_closed(gpointer user_data);
static gboolean delayed_cache_free(gpointer data)
{
Cache* cache = data;
@@ -261,13 +268,23 @@ static void do_reload(Cache* cache)
int i;
GFile* gf;
int new_n_files;
char **new_files = NULL;
/* DEBUG("Re-generation of cache is needed!"); */
/* DEBUG("call menu-cache-gen to re-generate the cache"); */
memcpy( buf, "REL:", 4 );
memcpy( buf + 4, cache->md5, 32 );
buf[36] = '\n';
buf[37] = '\0';
if( ! regenerate_cache( cache->menu_name, cache->lang_name, cache->cache_file,
cache->env, &new_n_files, &new_files ) )
{
DEBUG("regeneration of cache failed.");
return;
}
/* cancel old file monitors */
g_strfreev(cache->files);
for( i = 0; i < cache->n_files; ++i )
@@ -280,11 +297,9 @@ static void do_reload(Cache* cache)
g_file_monitor_cancel(cache->cache_mon);
g_object_unref(cache->cache_mon);
*/
if( ! regenerate_cache( cache->menu_name, cache->lang_name, cache->cache_file,
cache->env, &cache->n_files, &cache->files ) )
{
DEBUG("regeneration of cache failed.");
}
cache->n_files = new_n_files;
cache->files = new_files;
cache->mons = g_realloc( cache->mons, sizeof(GFileMonitor*)*(cache->n_files+1) );
/* create required file monitors */
@@ -309,9 +324,12 @@ static void do_reload(Cache* cache)
/* notify the clients that reload is needed. */
for( l = cache->clients; l; l = l->next )
{
GIOChannel* ch = (GIOChannel*)l->data;
ClientIO *channel_io = (ClientIO *)l->data;
GIOChannel* ch = channel_io->channel;
if(write(g_io_channel_unix_get_fd(ch), buf, 37) < 37)
g_io_channel_shutdown(ch, FALSE, NULL);
{
on_client_closed(channel_io);
}
}
cache->need_reload = FALSE;
}
@@ -321,10 +339,13 @@ static gboolean delayed_reload( Cache* cache )
if(g_source_is_destroyed(g_main_current_source()))
return FALSE;
cache->delayed_reload_handler = 0;
if(cache->need_reload)
do_reload(cache);
if (cache->need_reload)
return TRUE;
cache->delayed_reload_handler = 0;
return FALSE;
}
@@ -385,8 +406,12 @@ void on_file_changed( GFileMonitor* mon, GFile* gf, GFile* other,
g_source_remove(cache->delayed_reload_handler);
}
else
{
/* no reload in last 3 seconds... good, do it immediately */
/* mark need_reload anyway. If do_reload succeeds, it is cleaned up */
cache->need_reload = TRUE;
do_reload(cache);
}
cache->delayed_reload_handler = g_timeout_add_seconds_full( G_PRIORITY_LOW, 3, (GSourceFunc)delayed_reload, cache, NULL );
}
@@ -488,16 +513,18 @@ static int create_socket(struct sockaddr_un *addr)
static void on_client_closed(gpointer user_data)
{
GIOChannel* ch = user_data;
ClientIO* client_io = user_data;
GHashTableIter it;
char* md5;
Cache* cache;
GSList *l;
GIOChannel *ch = client_io->channel;
DEBUG("client closed: %p", ch);
g_hash_table_iter_init (&it, hash);
while( g_hash_table_iter_next (&it, (gpointer*)&md5, (gpointer*)&cache) )
{
while((l = g_slist_find( cache->clients, ch )) != NULL)
while((l = g_slist_find( cache->clients, client_io )) != NULL)
{
/* FIXME: some clients are closed accidentally without
* unregister the menu first due to crashes.
@@ -515,6 +542,9 @@ static void on_client_closed(gpointer user_data)
}
}
/* DEBUG("client closed"); */
g_source_remove(client_io->source_id);
g_free(client_io);
}
static gboolean on_client_data_in(GIOChannel* ch, GIOCondition cond, gpointer user_data)
@@ -529,15 +559,18 @@ static gboolean on_client_data_in(GIOChannel* ch, GIOCondition cond, gpointer us
if(cond & (G_IO_HUP|G_IO_ERR) )
{
on_client_closed(user_data);
return FALSE; /* remove the watch */
}
retry:
st = g_io_channel_read_line( ch, &line, &len, NULL, NULL );
if( st == G_IO_STATUS_AGAIN )
goto retry;
if( st != G_IO_STATUS_NORMAL )
if( st != G_IO_STATUS_NORMAL ) {
on_client_closed(user_data);
return FALSE;
}
--len;
line[len] = 0;
@@ -644,7 +677,7 @@ static gboolean on_client_data_in(GIOChannel* ch, GIOCondition cond, gpointer us
}
}
/* DEBUG("menu %s requested by client %d", md5, g_io_channel_unix_get_fd(ch)); */
cache->clients = g_slist_prepend(cache->clients, ch);
cache->clients = g_slist_prepend(cache->clients, user_data);
if(cache->delayed_free_handler)
{
g_source_remove(cache->delayed_free_handler);
@@ -670,7 +703,7 @@ static gboolean on_client_data_in(GIOChannel* ch, GIOCondition cond, gpointer us
if(cache && cache->clients)
{
/* remove the IO channel from the cache */
cache->clients = g_slist_remove(cache->clients, ch);
cache->clients = g_slist_remove(cache->clients, user_data);
if(cache->clients == NULL)
cache_free(cache);
}
@@ -688,6 +721,7 @@ static gboolean on_new_conn_incoming(GIOChannel* ch, GIOCondition cond, gpointer
socklen_t client_addrlen;
struct sockaddr client_addr;
GIOChannel* child;
ClientIO* client_io;
server = g_io_channel_unix_get_fd(ch);
@@ -701,8 +735,12 @@ static gboolean on_new_conn_incoming(GIOChannel* ch, GIOCondition cond, gpointer
child = g_io_channel_unix_new(client);
g_io_channel_set_close_on_unref( child, TRUE );
g_io_add_watch_full(child, G_PRIORITY_DEFAULT, G_IO_PRI|G_IO_IN|G_IO_HUP|G_IO_ERR,
on_client_data_in, child, on_client_closed);
client_io = g_new0 (ClientIO, 1);
client_io->channel = child;
client_io->source_id =
g_io_add_watch(child, G_IO_PRI|G_IO_IN|G_IO_HUP|G_IO_ERR,
on_client_data_in, client_io);
g_io_channel_unref(child);
DEBUG("new client accepted: %p", child);
@@ -808,7 +846,6 @@ int main(int argc, char** argv)
ch = g_io_channel_unix_new(server_fd);
if(!ch)
return 1;
g_io_channel_set_close_on_unref(ch, TRUE);
g_io_add_watch(ch, G_IO_IN|G_IO_PRI, on_new_conn_incoming, NULL);
g_io_add_watch(ch, G_IO_ERR, on_server_conn_close, NULL);
g_io_channel_unref(ch);

0 comments on commit 4a65262

Please sign in to comment.