static void sxe_dirwatch_event(EV_P_ ev_io * io, int revents) { char buffer[8192]; int length; unsigned offset; struct inotify_event * event; SXE_UNUSED_PARAMETER(revents); SXEE62("(fd=%d, revents=%08x)", io->fd, revents); SXEA11((length = read(io->fd, buffer, sizeof(buffer))) >= 0, "sxe_dirwatch_event: Failed to read events from inotify: %s", strerror(errno)); for (offset = 0; offset < (unsigned)length;) { SXE_LIST_WALKER walker; SXE_DIRWATCH * dirwatch; int flags = 0; SXEA12(length - offset >= sizeof(struct inotify_event), "Odd sized chunk left in buffer %u (expected inotify event of %u bytes)", length - offset, sizeof(struct inotify_event)); event = (struct inotify_event *)&buffer[offset]; offset += sizeof(struct inotify_event); SXEA12(length - offset >= event->len, "Chunk left in buffer %u (expected length %u)", length - offset, event->len); offset += event->len; SXEL63("dirwatch_event: fd=%d flags=%08x file=%s", event->wd, event->mask, event->name); sxe_list_walker_construct(&walker, &sxe_dirwatch_list); while ((dirwatch = (SXE_DIRWATCH *)sxe_list_walker_step(&walker)) != NULL) { if (dirwatch->fd == event->wd) { break; } } SXEA11(dirwatch, "No watched directory found with fd %d", event->wd); flags |= (event->mask & IN_CREATE) ? SXE_DIRWATCH_CREATED : 0; flags |= (event->mask & IN_MOVED_TO) ? SXE_DIRWATCH_CREATED : 0; flags |= (event->mask & IN_MODIFY) ? SXE_DIRWATCH_MODIFIED : 0; flags |= (event->mask & IN_DELETE) ? SXE_DIRWATCH_DELETED : 0; flags |= (event->mask & IN_MOVED_FROM) ? SXE_DIRWATCH_DELETED : 0; dirwatch->notify(EV_A_ event->name, flags, dirwatch->user_data); } SXER60("return"); }
/** * Construct a pool state walker (AKA iterator) * * @param walker Pointer to the walker * @param array Pointer to the pool array * @param state State to walk * * @exception If the pool is both locked and timed, it cannot be walked safely */ void sxe_pool_walker_construct(SXE_POOL_WALKER * walker, void * array, unsigned state) { SXE_POOL_IMPL * pool = SXE_POOL_ARRAY_TO_IMPL(array); SXEE83("sxe_pool_walker_construct(walker=%p,pool=%s,state=%s)", walker, pool->name, (*pool->state_to_string)(state)); SXEA11(!((pool->options & SXE_POOL_OPTION_LOCKED) && (pool->options & SXE_POOL_OPTION_TIMED)), "sxe_pool_walker_construct: Can't walk thread safe timed pool %s safely", pool->name); sxe_list_walker_construct(&walker->list_walker, &SXE_POOL_QUEUE(pool)[state]); walker->pool = pool; walker->state = state; if (pool->options & SXE_POOL_OPTION_TIMED) { walker->last.time = 0.0; } else { walker->last.count = 0; } SXER80("return"); }
/** * Step to the next object in a pool state * * @param walker Pointer to the pool state walker * * @return Index of the next object or SXE_POOL_NO_INDEX if the end of the state queue has been reached. * * @note Thread safety is implemented by verifying that the last node stepped to is still in the same state queue. If it is not, * the state queue is rewalked to find a node with a time or count greater than or equal to the time that the last stepped * to node had when it was stepped to. */ unsigned sxe_pool_walker_step(SXE_POOL_WALKER * walker) { SXE_POOL_NODE * node; SXE_POOL_IMPL * pool = walker->pool; unsigned result; SXEE81("sxe_pool_walker_step(walker=%p)", walker); if ((result = sxe_pool_lock(pool)) == SXE_POOL_LOCK_NOT_TAKEN) { goto SXE_ERROR_OUT; } /* If not at the head of the state queue and the current object has been moved to another state. */ if (((node = sxe_list_walker_find(&walker->list_walker)) != NULL) && (SXE_LIST_NODE_GET_ID(&node->list_node) != walker->state)) /* TODO: Check for touching */ { SXEL83("sxe_pool_walker_step: node %u moved from state %s to state %s by another thread", node - SXE_POOL_NODES(pool), (*pool->state_to_string)(walker->state), (*pool->state_to_string)(SXE_LIST_NODE_GET_ID(&node->list_node))); /* If there is a previous object and it has not been moved, get the new next one. */ if (((node = sxe_list_walker_back(&walker->list_walker)) != NULL) && (SXE_LIST_NODE_GET_ID(&node->list_node) == walker->state)) /* TODO: Check for touching */ { node = sxe_list_walker_step(&walker->list_walker); } else { sxe_list_walker_construct(&walker->list_walker, &SXE_POOL_QUEUE(pool)[walker->state]); while ((node = sxe_list_walker_step(&walker->list_walker)) != NULL) { if (pool->options & SXE_POOL_OPTION_TIMED) { if (node->last.time >= walker->last.time) { /* Coverage Exclusion: TODO refactor SXE_POOL_TIME */ break; /* Coverage Exclusion: TODO refactor SXE_POOL_TIME */ } } else { if (node->last.count >= walker->last.count) { break; } } } } } else { node = sxe_list_walker_step(&walker->list_walker); } result = SXE_POOL_NO_INDEX; if (node != NULL) { result = node - SXE_POOL_NODES(pool); if (pool->options & SXE_POOL_OPTION_TIMED) { walker->last.time = node->last.time; } else { walker->last.count = node->last.count; } } sxe_pool_unlock(pool); SXE_ERROR_OUT: SXER81("return %s", sxe_pool_return_to_string(result)); return result; }