Beispiel #1
0
/*
 * port_remove
 *
 * < private >
 * Unsafe, need lock fen_lock.
 */
void
port_remove (node_t *f)
{
    /* g_assert(f->source); */

    if (NODE_HAS_STATE(f, NODE_STATE_ASSOCIATED)) {
        /* Mark unregisted. */
        if (port_dissociate(PGPFD(f->source)->fd, PORT_SOURCE_FILE, (uintptr_t)FILE_OBJECT(f)) == 0) {
            /*
             * Note, we can run foode_delete if dissociating is failed,
             * because there may be some pending events (mostly like
             * FILE_DELETE) in the port_get. If we delete the foode
             * the fnode may be deleted, then port_get will run on an invalid
             * address.
             */
            NODE_CLE_STATE(f, NODE_STATE_ASSOCIATED);
            FK_W ("PORT_DISSOCIATE 0x%p OK\n", f);
        } else if (errno == ENOENT) {
            /* The file has been removed from port, after port_get or before
             * port_get but DELETED event has been generated.
             * Ignored. */
        } else {
            FK_W ("PORT_DISSOCIATE 0x%p %s\n", f, g_strerror (errno));
            g_return_if_reached();
        }
    }
}
Beispiel #2
0
static gboolean
port_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
{
    node_t *f;
	uint_t nget = 0;
	uint_t total = 0;

    FK_W ("%s 0x%p fd %d\n", __func__, source, PGPFD(source)->fd);

    G_LOCK (fen_lock);
    do {
        nget = 1;
        if (port_getn(PGPFD(source)->fd, pevents, PE_ALLOC, &nget, &zero_wait) == 0) {
            int i;
            for (i = 0; i < nget; i++) {
                f = (node_t *)pevents[i].portev_user;

                if (pevents[i].portev_source == PORT_SOURCE_FILE) {

                    NODE_CLE_STATE(f, NODE_STATE_ASSOCIATED);
                    NODE_SET_STATE(f, NODE_STATE_HAS_EVENTS);

                    if (HAS_NO_EXCEPTION_EVENTS(pevents[i].portev_events)) {
                        /* If the events do not show it's deleted, update
                         * file timestamp to avoid missing events next time.
                         */
                        if (node_lstat(f) != 0 /* || port_add(f) != 0 */) {
                            /* Included deleted event. */
                            pevents[i].portev_events |= FILE_DELETE;
                        }
                    }

                    /* Queue it and waiting for processing. */
                    g_queue_push_tail(g_eventq,
                      node_event_new(pevents[i].portev_events, (gpointer)f));

                } else {
                    FK_W ("[kernel] unknown portev_source %d\n", pevents[i].portev_source);
                }
            }

            total += nget;

        } else {
            FK_W ("[kernel] port_getn %s\n", g_strerror (errno));
            break;
        }
    } while (nget == PE_ALLOC);

    G_UNLOCK (fen_lock);

    if (total > 0 && callback) {
        FK_W ("[kernel] get total %ld events\n", total);
        return callback (user_data);
    }
    return TRUE;
}
Beispiel #3
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);
}