diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2012-09-13 16:18:54 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2012-09-13 16:18:54 +0200 |
commit | dd1b9477063e39c5d916ebb602947340442d4d50 (patch) | |
tree | 01cc3cc477c26c8d529f7fd7db67aa8fcaccb974 /deps/uv/src/unix/fsevents.c | |
parent | 2c97da82f5e23beb3f78258bb1340e63895e5125 (diff) | |
download | android-node-v8-dd1b9477063e39c5d916ebb602947340442d4d50.tar.gz android-node-v8-dd1b9477063e39c5d916ebb602947340442d4d50.tar.bz2 android-node-v8-dd1b9477063e39c5d916ebb602947340442d4d50.zip |
deps: upgrade libuv to 1f9bd99
Diffstat (limited to 'deps/uv/src/unix/fsevents.c')
-rw-r--r-- | deps/uv/src/unix/fsevents.c | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c new file mode 100644 index 0000000000..1a7e06e46c --- /dev/null +++ b/deps/uv/src/unix/fsevents.c @@ -0,0 +1,225 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include <assert.h> +#include <stdlib.h> +#include <CoreServices/CoreServices.h> + +typedef struct uv__fsevents_event_s uv__fsevents_event_t; + +struct uv__fsevents_event_s { + int events; + ngx_queue_t member; + char path[1]; +}; + + +#define UV__FSEVENTS_WALK(handle, block) \ + { \ + ngx_queue_t* curr; \ + ngx_queue_t split_head; \ + uv__fsevents_event_t* event; \ + uv_mutex_lock(&(handle)->cf_mutex); \ + ngx_queue_init(&split_head); \ + if (!ngx_queue_empty(&(handle)->cf_events)) { \ + ngx_queue_t* split_pos = ngx_queue_next(&(handle)->cf_events); \ + ngx_queue_split(&(handle)->cf_events, split_pos, &split_head); \ + } \ + uv_mutex_unlock(&(handle)->cf_mutex); \ + while (!ngx_queue_empty(&split_head)) { \ + curr = ngx_queue_head(&split_head); \ + /* Invoke callback */ \ + event = ngx_queue_data(curr, uv__fsevents_event_t, member); \ + ngx_queue_remove(curr); \ + /* Invoke block code, but only if handle wasn't closed */ \ + if (((handle)->flags & (UV_CLOSING | UV_CLOSED)) == 0) \ + block \ + /* Free allocated data */ \ + free(event); \ + } \ + } + + +void uv__fsevents_cb(uv_async_t* cb, int status) { + uv_fs_event_t* handle; + + handle = cb->data; + + UV__FSEVENTS_WALK(handle, { + if (handle->fd != -1) + handle->cb(handle, event->path, event->events, 0); + }) + + if ((handle->flags & (UV_CLOSING | UV_CLOSED)) == 0 && handle->fd == -1) + uv__fsevents_close(handle); +} + + +void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, + void* info, + size_t numEvents, + void* eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]) { + size_t i; + int len; + char** paths; + uv_fs_event_t* handle; + uv__fsevents_event_t* event; + ngx_queue_t add_list; + + handle = info; + paths = eventPaths; + ngx_queue_init(&add_list); + + for (i = 0; i < numEvents; i++) { + /* Ignore system events */ + if (eventFlags[i] & (kFSEventStreamEventFlagUserDropped | + kFSEventStreamEventFlagKernelDropped | + kFSEventStreamEventFlagEventIdsWrapped | + kFSEventStreamEventFlagHistoryDone | + kFSEventStreamEventFlagMount | + kFSEventStreamEventFlagUnmount)) { + continue; + } + + /* TODO: Report errors */ + len = strlen(paths[i]); + event = malloc(sizeof(*event) + len); + if (event == NULL) + break; + + memcpy(event->path, paths[i], len + 1); + + if (eventFlags[i] & kFSEventStreamEventFlagItemModified) + event->events = UV_CHANGE; + else + event->events = UV_RENAME; + + ngx_queue_insert_tail(&add_list, &event->member); + } + uv_mutex_lock(&handle->cf_mutex); + ngx_queue_add(&handle->cf_events, &add_list); + uv_mutex_unlock(&handle->cf_mutex); + + uv_async_send(handle->cf_cb); +} + + +void uv__fsevents_schedule(void* arg) { + uv_fs_event_t* handle; + + handle = arg; + FSEventStreamScheduleWithRunLoop(handle->cf_eventstream, + handle->loop->cf_loop, + kCFRunLoopDefaultMode); + FSEventStreamStart(handle->cf_eventstream); + uv_sem_post(&handle->cf_sem); +} + + +int uv__fsevents_init(uv_fs_event_t* handle) { + FSEventStreamContext ctx; + FSEventStreamRef ref; + CFStringRef path; + CFArrayRef paths; + CFAbsoluteTime latency; + FSEventStreamCreateFlags flags; + + /* Initialize context */ + ctx.version = 0; + ctx.info = handle; + ctx.retain = NULL; + ctx.release = NULL; + ctx.copyDescription = NULL; + + /* Initialize paths array */ + path = CFStringCreateWithCString(NULL, + handle->filename, + CFStringGetSystemEncoding()); + paths = CFArrayCreate(NULL, (const void**)&path, 1, NULL); + + latency = 0.15; + + /* Set appropriate flags */ + flags = kFSEventStreamCreateFlagFileEvents; + + ref = FSEventStreamCreate(NULL, + &uv__fsevents_event_cb, + &ctx, + paths, + kFSEventStreamEventIdSinceNow, + latency, + flags); + handle->cf_eventstream = ref; + + /* + * Events will occur in other thread. + * Initialize callback for getting them back into event loop's thread + */ + handle->cf_cb = malloc(sizeof(*handle->cf_cb)); + if (handle->cf_cb == NULL) + return uv__set_sys_error(handle->loop, ENOMEM); + + handle->cf_cb->data = handle; + uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb); + handle->cf_cb->flags |= UV__HANDLE_INTERNAL; + uv_unref((uv_handle_t*) handle->cf_cb); + + uv_mutex_init(&handle->cf_mutex); + uv_sem_init(&handle->cf_sem, 0); + ngx_queue_init(&handle->cf_events); + + uv__cf_loop_signal(handle->loop, uv__fsevents_schedule, handle); + + return 0; +} + + +int uv__fsevents_close(uv_fs_event_t* handle) { + if (handle->cf_eventstream == NULL) + return -1; + + /* Ensure that event stream was scheduled */ + uv_sem_wait(&handle->cf_sem); + + /* Stop emitting events */ + FSEventStreamStop(handle->cf_eventstream); + + /* Release stream */ + FSEventStreamInvalidate(handle->cf_eventstream); + FSEventStreamRelease(handle->cf_eventstream); + handle->cf_eventstream = NULL; + + uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) free); + + /* Free data in queue */ + UV__FSEVENTS_WALK(handle, { + /* NOP */ + }) + + uv_mutex_destroy(&handle->cf_mutex); + uv_sem_destroy(&handle->cf_sem); + + return 0; +} |