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