/* * 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(); } } }
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; }
/* * 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; }