/** * fen_add * * Won't hold a ref, we have a timout callback to clean unused node_t. * If there is no value for a key, add it and return it; else return the old * one. */ void fen_add (const gchar *filename, gpointer sub, gboolean is_mondir) { node_t* f; g_assert (filename); g_assert (sub); G_LOCK (fen_lock); f = node_find(NULL, filename, TRUE); FH_W ("%s 0x%p sub[0x%p] %s\n", __func__, f, sub, filename); g_assert (f); /* Update timestamp, the events in global queue will compare itself to this * timestamp to decide if be emitted. TODO, timestamp should be per sub. */ if (!NODE_IS_ACTIVE(f)) { g_get_current_time(&f->atv); } if (is_mondir) { f->dir_subs = g_list_prepend(f->dir_subs, sub); } else { f->subs = g_list_prepend(f->subs, sub); } if (NODE_HAS_STATE(f, NODE_STATE_ASSOCIATED) || (node_lstat(f) == 0 && port_add(f) == 0)) { #ifndef GIO_COMPILATION gam_server_emit_one_event (NODE_NAME(f), gam_subscription_is_dir (sub), GAMIN_EVENT_EXISTS, sub, 1); #endif if (is_mondir) { scan_children_init (f, sub); } } else { #ifndef GIO_COMPILATION gam_server_emit_one_event (NODE_NAME(f), gam_subscription_is_dir (sub), GAMIN_EVENT_DELETED, sub, 1); #endif node_adjust_deleted (f); } #ifndef GIO_COMPILATION gam_server_emit_one_event (NODE_NAME(f), gam_subscription_is_dir (sub), GAMIN_EVENT_ENDEXISTS, sub, 1); #endif G_UNLOCK (fen_lock); }
/** * Adds a subscription to be monitored. * * @param sub a #GamSubscription to be polled * @returns TRUE if adding the subscription succeeded, FALSE otherwise */ gboolean gam_kqueue_add_subscription (GamSubscription *sub) { const char *path; GHashTable *hash; SubMonitor *smon; gam_listener_add_subscription(gam_subscription_get_listener(sub), sub); path = gam_subscription_get_path(sub); hash = gam_subscription_is_dir(sub) ? dir_hash : file_hash; smon = g_hash_table_lookup(hash, path); if (smon) { smon->subs = g_list_append(smon->subs, sub); return TRUE; } smon = gam_kqueue_sub_monitor_new(sub); smon->subs = g_list_append(smon->subs, sub); g_hash_table_insert(hash, MONITOR(smon)->pathname, smon); gam_kqueue_sub_monitor_enable_notification(smon, 0); return TRUE; }
static void node_emit_one_event(node_t *f, GList *subs, node_t *other, int event) { GList* idx; FN_W ("%s %s %d\n", __func__, NODE_NAME(f), event); #ifdef GIO_COMPILATION for (idx = subs; idx; idx = idx->next) { g_file_monitor_emit_event(G_FILE_MONITOR(idx->data), f->gfile, (other == NULL ? NULL : other->gfile), event); } #else for (idx = subs; idx; idx = idx->next) { gam_server_emit_one_event(NODE_NAME(f), gam_subscription_is_dir(idx->data), event, idx->data, 1); } #endif }
static SubMonitor * gam_kqueue_sub_monitor_new (GamSubscription *sub) { SubMonitor *smon; Monitor *mon; smon = g_new0(SubMonitor, 1); mon = MONITOR(smon); mon->handle_kevent = gam_kqueue_sub_monitor_handle_kevent; mon->pathname = g_strdup(gam_subscription_get_path(sub)); mon->fd = -1; smon->isdir = gam_subscription_is_dir(sub); gam_kqueue_sub_monitor_init_fmons(smon); return smon; }
/** * Removes a subscription which was being monitored. * * @param sub a #GamSubscription to remove * @returns TRUE if removing the subscription succeeded, FALSE otherwise */ gboolean gam_kqueue_remove_subscription (GamSubscription *sub) { GHashTable *hash; SubMonitor *smon; hash = gam_subscription_is_dir(sub) ? dir_hash : file_hash; smon = g_hash_table_lookup(hash, gam_subscription_get_path(sub)); if (! smon) return FALSE; smon->subs = g_list_remove_all(smon->subs, sub); if (! smon->subs) { g_hash_table_remove(hash, MONITOR(smon)->pathname); gam_kqueue_sub_monitor_free(smon); } gam_subscription_cancel(sub); return TRUE; }
/* misc */ static void scan_children_init(node_t *f, gpointer sub) { gboolean emit; gint event; FH_W ("%s %s [0x%p]\n", __func__, NODE_NAME(f), f); #ifdef GIO_COMPILATION emit = FALSE; event = G_FILE_MONITOR_EVENT_CREATED; #else emit = TRUE; event = GAMIN_EVENT_EXISTS; #endif if (!NODE_HAS_FLAG(f, NODE_FLAG_SNAPSHOT_UPDATED)) { /* TODO snapshot should also compare to the sub created timestamp. */ /* GIO initially doesn't emit created/existed events. */ node_create_children_snapshot(f, event, emit); } else { GHashTableIter iter; gpointer value; g_hash_table_iter_init (&iter, f->children); while (g_hash_table_iter_next (&iter, NULL, &value)) { node_t *child = (node_t *)value; #ifdef GIO_COMPILATION /* GIO initially doesn't emit created/existed events. */ /* g_file_monitor_emit_event(G_FILE_MONITOR(sub), child->gfile, NULL, event); */ #else gam_server_emit_one_event(NODE_NAME(child), gam_subscription_is_dir(sub), event, sub, 1); #endif } } }