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
gint
node_lstat(node_t *f)
{
    struct stat buf;

    g_assert(!NODE_HAS_STATE(f, NODE_STATE_ASSOCIATED));

    if (lstat(NODE_NAME(f), &buf) == 0) {
        FN_W ("%s %s\n", __func__, NODE_NAME(f));
        FILE_OBJECT(f)->fo_atime = buf.st_atim;
        FILE_OBJECT(f)->fo_mtime = buf.st_mtim;
        FILE_OBJECT(f)->fo_ctime = buf.st_ctim;
        NODE_SET_FLAG(f, NODE_FLAG_STAT_UPDATED |
          (S_ISDIR (buf.st_mode) ? NODE_FLAG_DIR : NODE_FLAG_NONE));
        return 0;
    } else {
        FN_W ("%s(lstat) %s %s\n", __func__, NODE_NAME(f), g_strerror (errno));
    }
    return errno;
}
Beispiel #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;
}