Esempio n. 1
0
/* 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
        }
    }
}
Esempio n. 2
0
/*
 * node_add_event:
 *
 */
static void
node_add_event (node_t *f, node_event_t *ev)
{
    FN_W ("%s %d\n", __func__, ev->e);

    /* Clean the events flag early, because all received events need be
     * processed in this function.
     */
    NODE_CLE_STATE(f, NODE_STATE_HAS_EVENTS);

    /*
     * Node the node has been created, so we can delete create event in
     * optimizing. To reduce the statings, we add it to Port on discoving
     * it then emit CREATED event. So we don't need to do anything here.
     */
    if (NODE_NEED_MONITOR(f)) {
        if (HAS_NO_EXCEPTION_EVENTS(ev->e)) {
            if (NODE_HAS_STATE(f, NODE_STATE_ASSOCIATED) || port_add(f) == 0) {
                if ((ev->e & FILE_MODIFIED) && NODE_HAS_FLAG(f, NODE_FLAG_DIR)) {
                    if (f->dir_subs) {
                        node_create_children_snapshot(f, FN_EVENT_CREATED, TRUE);
                    } else {
                        g_hash_table_foreach(f->children, foreach_known_children_scan, NULL);
                    }
                }
            } else {
                /* Emit delete event */
                ev->e |= FILE_DELETE;

                node_adjust_deleted(f);
            }

        } else {
            node_adjust_deleted(f);
        }

        /* Send events to clients. */
        node_emit_events (f, ev);
        
    } else {
        /* Send events to clients. */
        node_emit_events (f, ev);

        node_try_delete(f);
    }

    if (ev->pair_data) {
        node_t *from = ev->pair_data;
        g_assert(ev->e == FILE_RENAME_TO);

        if (NODE_NEED_MONITOR(from)) {
            /* Clean the events flag, since it may block free this node. */
            NODE_CLE_STATE(from, NODE_STATE_HAS_EVENTS);
            node_adjust_deleted(from);
        } else {
            node_try_delete(from);
        }
    }

    node_event_delete (ev);
}
Esempio n. 3
0
/*
 * port_add:
 * @f:
 *
 * Unsafe, need lock fen_lock.
 * port_add will associate a GSource to @f->source
 */
gint
port_add(node_t *f)
{
	GSource *source = f->source;

    FK_W ("%s [0x%p] %s\n", __func__, f, NODE_NAME(f));

    g_assert(f);
    g_assert(NODE_HAS_FLAG(f, NODE_FLAG_STAT_UPDATED));

    /* if (!NODE_HAS_FLAG(f, NODE_FLAG_STAT_DONE)) { */
    /*     if (NODE_STAT(f) != 0) { */
    /*         return errno; */
    /*     } */
    /* } */

    /* Try re-use f->pn. f->pn may be used by other request, e.g. f is deleted
     * for a long time. So if pn is full, we try to open a new one.
     */
    if (!source) {
start_over:
        /* Try the next visible source. */
        if (pn_visible_list) {
            source = (GSource *)pn_visible_list->data;
        } else {
            if ((source = psource_new()) != NULL) {
                g_assert (g_list_find (pn_visible_list, source) == NULL);
                pn_visible_list = g_list_prepend (pn_visible_list, source);
            }
        }
    }

    if (port_associate(PGPFD(source)->fd, PORT_SOURCE_FILE, (uintptr_t)FILE_OBJECT(f),
        CONCERNED_EVENTS,
        (void *)f) == 0) {
        f->source = source;
        NODE_SET_STATE(f, NODE_STATE_ASSOCIATED);
        NODE_CLE_FLAG(f, NODE_FLAG_STAT_UPDATED);
        FK_W ("PORT_ASSOCIATE 0x%p OK\n", f);
        return 0;
    } else if (errno == EAGAIN) {
        /* Full, remove it. */
        pn_visible_list = g_list_remove (pn_visible_list, source);
        /* Re-add to port */
        goto start_over;

    } else if (errno == ENOENT) {
        /* File is not exist */
    } else if (errno == ENOTSUP) {
        /* FS is not supported. Currently we think it no longer make sense to
         * monitor it, so clean the stat info and return 0 to ignore this
         * node. If there are requirement, we can consider to add polling
         * method.
         */
        NODE_CLE_FLAG(f, NODE_FLAG_STAT_UPDATED);
        return 0;
    } else {
        FK_W ("PORT_ASSOCIATE 0x%p %s\n", f, g_strerror (errno));
    }

    /* No matter if associated successfully, stat info is out-of-date, so clean it. */
    NODE_CLE_FLAG(f, NODE_FLAG_STAT_UPDATED);
    return errno;
}