diff options
-rw-r--r-- | deps/uv/README | 7 | ||||
-rw-r--r-- | deps/uv/config-unix.mk | 11 | ||||
-rw-r--r-- | deps/uv/create-msvs-files.bat | 21 | ||||
-rw-r--r-- | deps/uv/include/uv-unix.h | 8 | ||||
-rw-r--r-- | deps/uv/include/uv-win.h | 19 | ||||
-rw-r--r-- | deps/uv/include/uv.h | 96 | ||||
-rw-r--r-- | deps/uv/src/eio/eio.c | 29 | ||||
-rw-r--r-- | deps/uv/src/unix/fs.c | 294 | ||||
-rw-r--r-- | deps/uv/src/unix/internal.h | 34 | ||||
-rw-r--r-- | deps/uv/src/uv-common.h | 7 | ||||
-rw-r--r-- | deps/uv/src/uv-unix.c | 18 | ||||
-rw-r--r-- | deps/uv/src/win/core.c | 3 | ||||
-rw-r--r-- | deps/uv/src/win/fs.c | 733 | ||||
-rw-r--r-- | deps/uv/src/win/internal.h | 13 | ||||
-rw-r--r-- | deps/uv/src/win/req.c | 8 | ||||
-rw-r--r-- | deps/uv/src/win/threadpool.c | 69 | ||||
-rw-r--r-- | deps/uv/test/test-fs.c | 541 | ||||
-rw-r--r-- | deps/uv/test/test-list.h | 12 | ||||
-rw-r--r-- | deps/uv/test/test-threadpool.c | 59 | ||||
-rw-r--r-- | deps/uv/uv.gyp | 30 |
20 files changed, 1958 insertions, 54 deletions
diff --git a/deps/uv/README b/deps/uv/README index 8a12b46b6..c808c976b 100644 --- a/deps/uv/README +++ b/deps/uv/README @@ -15,10 +15,13 @@ To build via Makefile simply execute: make -To build with Visual Studio run the create-msvs-files.bat file which will -checkout the GYP code into build/gyp and generate the build/all.sln and +To build with Visual Studio run the vcbuilds.bat file which will +checkout the GYP code into build/gyp and generate the uv.sln and related files. +Windows users can also build from cmd-line using msbuild. This is +done by running vcbuild.bat from Visual Studio command prompt. + To have GYP generate build script for another system you will need to checkout GYP into the project tree manually: diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index ee8848e57..24e8f2dc9 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -85,15 +85,18 @@ endif RUNNER_LIBS= RUNNER_SRC=test/runner-unix.c -uv.a: src/uv-unix.o src/uv-common.o src/uv-platform.o src/ev/ev.o src/uv-eio.o src/eio/eio.o $(CARES_OBJS) - $(AR) rcs uv.a src/uv-unix.o src/uv-platform.o src/uv-common.o src/uv-eio.o src/ev/ev.o \ +uv.a: src/uv-unix.o src/unix/fs.o src/uv-common.o src/uv-platform.o src/ev/ev.o src/uv-eio.o src/eio/eio.o $(CARES_OBJS) + $(AR) rcs uv.a src/uv-unix.o src/unix/fs.o src/uv-platform.o src/uv-common.o src/uv-eio.o src/ev/ev.o \ src/eio/eio.o $(CARES_OBJS) src/uv-platform.o: src/$(UV_OS_FILE) include/uv.h include/uv-unix.h $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c src/$(UV_OS_FILE) -o src/uv-platform.o -src/uv-unix.o: src/uv-unix.c include/uv.h include/uv-unix.h - $(CC) $(CSTDFLAG) $(CPPFLAGS) -Ieio $(CFLAGS) -c src/uv-unix.c -o src/uv-unix.o +src/uv-unix.o: src/uv-unix.c include/uv.h include/uv-unix.h src/unix/internal.h + $(CC) $(CSTDFLAG) $(CPPFLAGS) -Isrc $(CFLAGS) -c src/uv-unix.c -o src/uv-unix.o + +src/unix/fs.o: src/unix/fs.c include/uv.h include/uv-unix.h src/unix/internal.h + $(CC) $(CSTDFLAG) $(CPPFLAGS) -Isrc/ $(CFLAGS) -c src/unix/fs.c -o src/unix/fs.o src/uv-common.o: src/uv-common.c include/uv.h include/uv-unix.h $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c src/uv-common.c -o src/uv-common.o diff --git a/deps/uv/create-msvs-files.bat b/deps/uv/create-msvs-files.bat deleted file mode 100644 index a83358bc4..000000000 --- a/deps/uv/create-msvs-files.bat +++ /dev/null @@ -1,21 +0,0 @@ -@echo off - -cd %~dp0 - -if exist build\gyp goto have_gyp - -echo svn co http://gyp.googlecode.com/svn/trunk@983 build/gyp -svn co http://gyp.googlecode.com/svn/trunk@983 build/gyp -if errorlevel 1 goto gyp_install_failed -goto have_gyp - -:gyp_install_failed -echo Failed to download gyp. Make sure you have subversion installed, or -echo manually install gyp into %~dp0build\gyp. -goto exit - -:have_gyp -python gyp_uv -if not errorlevel 1 echo Done. - -:exit diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv-unix.h index e918e4d47..9ceae197a 100644 --- a/deps/uv/include/uv-unix.h +++ b/deps/uv/include/uv-unix.h @@ -25,6 +25,7 @@ #include "ngx-queue.h" #include "ev.h" +#include "eio.h" #include <sys/types.h> #include <sys/socket.h> @@ -39,6 +40,8 @@ typedef struct { size_t len; } uv_buf_t; +typedef int uv_file; + #define UV_REQ_BUFSML_SIZE (4) #define UV_REQ_PRIVATE_FIELDS /* empty */ @@ -155,4 +158,9 @@ typedef struct { #define UV_PROCESS_PRIVATE_FIELDS \ ev_child child_watcher; +#define UV_FS_PRIVATE_FIELDS \ + eio_req* eio; + +#define UV_WORK_PRIVATE_FIELDS + #endif /* UV_UNIX_H */ diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h index 06966d5c2..438b18fce 100644 --- a/deps/uv/include/uv-win.h +++ b/deps/uv/include/uv-win.h @@ -42,6 +42,8 @@ typedef struct uv_buf_t { char* base; } uv_buf_t; +typedef int uv_file; + #define UV_REQ_TYPE_PRIVATE \ /* TODO: remove the req suffix */ \ UV_ARES_EVENT_REQ, \ @@ -208,5 +210,22 @@ typedef struct uv_buf_t { HANDLE process_handle; \ HANDLE close_handle; +#define UV_FS_PRIVATE_FIELDS \ + int flags; \ + void* arg0; \ + union { \ + struct { \ + void* arg1; \ + void* arg2; \ + void* arg3; \ + }; \ + struct { \ + ssize_t arg4; \ + ssize_t arg5; \ + }; \ + }; + +#define UV_WORK_PRIVATE_FIELDS \ + int uv_utf16_to_utf8(const wchar_t* utf16Buffer, size_t utf16Size, char* utf8Buffer, size_t utf8Size); int uv_utf8_to_utf16(const char* utf8Buffer, wchar_t* utf16Buffer, size_t utf16Size); diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 701599aa0..2efd4f683 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -60,6 +60,8 @@ typedef struct uv_shutdown_s uv_shutdown_t; typedef struct uv_write_s uv_write_t; typedef struct uv_connect_s uv_connect_t; typedef struct uv_udp_send_s uv_udp_send_t; +typedef struct uv_fs_s uv_fs_t; +typedef struct uv_work_s uv_work_t; #if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__) # include "uv-unix.h" @@ -123,6 +125,9 @@ typedef void (*uv_check_cb)(uv_check_t* handle, int status); typedef void (*uv_idle_cb)(uv_idle_t* handle, int status); typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* handle, int status, struct addrinfo* res); typedef void (*uv_exit_cb)(uv_process_t*, int exit_status, int term_signal); +typedef void (*uv_fs_cb)(uv_fs_t* req); +typedef void (*uv_work_cb)(uv_work_t* req); +typedef void (*uv_after_work_cb)(uv_work_t* req); /* Expand this list if necessary. */ @@ -199,6 +204,8 @@ typedef enum { UV_SHUTDOWN, UV_WAKEUP, UV_UDP_SEND, + UV_FS, + UV_WORK, UV_REQ_TYPE_PRIVATE } uv_req_type; @@ -801,6 +808,91 @@ int uv_spawn(uv_process_t*, uv_process_options_t options); int uv_process_kill(uv_process_t*, int signum); +/* + * uv_work_t is a subclass of uv_req_t + */ +struct uv_work_s { + UV_REQ_FIELDS + uv_work_cb work_cb; + uv_after_work_cb after_work_cb; + UV_WORK_PRIVATE_FIELDS +}; + +/* Queues a work request to execute asynchronously on the thread pool. */ +int uv_queue_work(uv_work_t* req, uv_work_cb work_cb, uv_after_work_cb after_work_cb); + + +typedef enum { + UV_FS_UNKNOWN = -1, + UV_FS_CUSTOM, + UV_FS_OPEN, + UV_FS_CLOSE, + UV_FS_READ, + UV_FS_WRITE, + UV_FS_SENDFILE, + UV_FS_STAT, + UV_FS_LSTAT, + UV_FS_FSTAT, + UV_FS_FTRUNCATE, + UV_FS_UTIME, + UV_FS_FUTIME, + UV_FS_CHMOD, + UV_FS_FCHMOD, + UV_FS_FSYNC, + UV_FS_FDATASYNC, + UV_FS_UNLINK, + UV_FS_RMDIR, + UV_FS_MKDIR, + UV_FS_RENAME, + UV_FS_READDIR, + UV_FS_LINK, + UV_FS_SYMLINK, + UV_FS_READLINK, + UV_FS_CHOWN, + UV_FS_FCHOWN +} uv_fs_type; + +/* + * uv_fs_t is a subclass of uv_req_t + */ +struct uv_fs_s { + UV_REQ_FIELDS + uv_fs_type fs_type; + uv_fs_cb cb; + ssize_t result; + void* ptr; + int errorno; + UV_FS_PRIVATE_FIELDS +}; + +void uv_fs_req_cleanup(uv_fs_t* req); +int uv_fs_close(uv_fs_t* req, uv_file file, uv_fs_cb cb); +int uv_fs_open(uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb); +int uv_fs_read(uv_fs_t* req, uv_file file, void* buf, size_t length, off_t offset, uv_fs_cb cb); +int uv_fs_unlink(uv_fs_t* req, const char* path, uv_fs_cb cb); +int uv_fs_write(uv_fs_t* req, uv_file file, void* buf, size_t length, off_t offset, uv_fs_cb cb); +int uv_fs_mkdir(uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); +int uv_fs_rmdir(uv_fs_t* req, const char* path, uv_fs_cb cb); +int uv_fs_readdir(uv_fs_t* req, const char* path, int flags, uv_fs_cb cb); +int uv_fs_stat(uv_fs_t* req, const char* path, uv_fs_cb cb); +int uv_fs_fstat(uv_fs_t* req, uv_file file, uv_fs_cb cb); +int uv_fs_rename(uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); +int uv_fs_fsync(uv_fs_t* req, uv_file file, uv_fs_cb cb); +int uv_fs_fdatasync(uv_fs_t* req, uv_file file, uv_fs_cb cb); +int uv_fs_ftruncate(uv_fs_t* req, uv_file file, off_t offset, uv_fs_cb cb); +int uv_fs_sendfile(uv_fs_t* req, uv_file out_fd, uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb); +int uv_fs_chmod(uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); +int uv_fs_utime(uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb); +int uv_fs_futime(uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb); +int uv_fs_lstat(uv_fs_t* req, const char* path, uv_fs_cb cb); +int uv_fs_link(uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); +int uv_fs_symlink(uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); +int uv_fs_readlink(uv_fs_t* req, const char* path, uv_fs_cb cb); +int uv_fs_fchmod(uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb); +int uv_fs_chown(uv_fs_t* req, const char* path, int uid, int gid, uv_fs_cb cb); +int uv_fs_fchown(uv_fs_t* req, uv_file file, int uid, int gid, uv_fs_cb cb); + + /* Utility */ /* Convert string ip addresses to binary structures */ @@ -843,6 +935,8 @@ union uv_any_req { uv_write_t write; uv_connect_t connect; uv_shutdown_t shutdown; + uv_fs_t fs_req; + uv_work_t work_req; }; @@ -876,6 +970,8 @@ uv_counters_t* uv_counters(); #undef UV_ASYNC_PRIVATE_FIELDS #undef UV_TIMER_PRIVATE_FIELDS #undef UV_GETADDRINFO_PRIVATE_FIELDS +#undef UV_FS_REQ_PRIVATE_FIELDS +#undef UV_WORK_PRIVATE_FIELDS #ifdef __cplusplus } diff --git a/deps/uv/src/eio/eio.c b/deps/uv/src/eio/eio.c index 8fd271152..a005db5d3 100644 --- a/deps/uv/src/eio/eio.c +++ b/deps/uv/src/eio/eio.c @@ -180,8 +180,8 @@ static void eio_destroy (eio_req *req); static int symlink (const char *old, const char *neu) { - #if 0 && WINVER >= 0x0600 - if (CreateSymbolicLink (neu, old, SYMBOLIC_LINK_FLAG_DIRECTORY)) + #if WINVER >= 0x0600 + if (CreateSymbolicLink (neu, old, 1)) return 0; if (CreateSymbolicLink (neu, old, 0)) @@ -401,6 +401,16 @@ static xmutex_t reslock; static xmutex_t reqlock; static xcond_t reqwait; +/* Fix for test-fs-sir-writes-alot */ +/* Apple's OSX can't safely write() concurrently from 2 threads */ +/* for more info see the thread "fs.write Data Munging" in the nodejs google group */ +/* http://groups.google.com/group/nodejs/browse_thread/thread/c11f8b683f37cef/b18ad9e0a15314c5 */ +/* And the thread "write()s and pwrite()s from multiple threads in OSX" in libev@lists.schmorp.de */ +/* http://lists.schmorp.de/pipermail/libev/2010q4/001185.html */ +#if defined (__APPLE__) +static xmutex_t apple_bug_writelock = X_MUTEX_INIT; +#endif + #if !HAVE_PREADWRITE /* * make our pread/pwrite emulation safe against themselves, but not against @@ -2153,9 +2163,20 @@ eio_execute (etp_worker *self, eio_req *req) req->result = req->offs >= 0 ? pread (req->int1, req->ptr2, req->size, req->offs) : read (req->int1, req->ptr2, req->size); break; - case EIO_WRITE: req->result = req->offs >= 0 + + case EIO_WRITE: +#if defined (__APPLE__) + pthread_mutex_lock (&apple_bug_writelock); +#endif + + req->result = req->offs >= 0 ? pwrite (req->int1, req->ptr2, req->size, req->offs) - : write (req->int1, req->ptr2, req->size); break; + : write (req->int1, req->ptr2, req->size); + +#if defined (__APPLE__) + pthread_mutex_unlock (&apple_bug_writelock); +#endif + break; case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break; case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break; diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c new file mode 100644 index 000000000..51919ce90 --- /dev/null +++ b/deps/uv/src/unix/fs.c @@ -0,0 +1,294 @@ +/* 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 "eio.h" + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + + +static void uv_fs_req_init(uv_fs_t* req, uv_fs_type fs_type, uv_fs_cb cb) { + uv__req_init((uv_req_t*) req); + req->type = UV_FS; + req->fs_type = fs_type; + req->cb = cb; + req->result = 0; + req->ptr = NULL; + req->errorno = 0; + req->eio = NULL; +} + + +void uv_fs_req_cleanup(uv_fs_t* req) { + assert(0 && "implement me"); +} + + +static int uv__fs_after(eio_req* eio) { + uv_fs_t* req = eio->data; + assert(req->cb); + + req->result = req->eio->result; + req->eio = NULL; /* Freed by libeio */ + + req->cb(req); + return 0; +} + + +int uv_fs_close(uv_fs_t* req, uv_file file, uv_fs_cb cb) { + uv_fs_req_init(req, UV_FS_CLOSE, cb); + if (cb) { + /* async */ + req->eio = eio_close(file, EIO_PRI_DEFAULT, uv__fs_after, req); + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + } else { + /* sync */ + if ((req->result = uv__close(file))) { + uv_err_new(NULL, errno); + return -1; + } + } + + return 0; +} + + +int uv_fs_open(uv_fs_t* req, const char* path, int flags, int mode, + uv_fs_cb cb) { + uv_fs_req_init(req, UV_FS_OPEN, cb); + + if (cb) { + /* async */ + req->eio = eio_open(path, flags, mode, EIO_PRI_DEFAULT, uv__fs_after, req); + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + + } else { + /* sync */ + req->result = open(path, flags, mode); + if (req->result < 0) { + uv_err_new(NULL, errno); + return -1; + } + + uv__cloexec(req->result, 1); + } + + return 0; +} + + +int uv_fs_read(uv_fs_t* req, uv_file fd, void* buf, size_t length, + off_t offset, uv_fs_cb cb) { + uv_fs_req_init(req, UV_FS_READ, cb); + + if (cb) { + /* async */ + req->eio = eio_read(fd, buf, length, offset, EIO_PRI_DEFAULT, + uv__fs_after, req); + + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + + } else { + /* sync */ + req->result = offset < 0 ? + read(fd, buf, length) : + pread(fd, buf, length, offset); + + if (req->result < 0) { + uv_err_new(NULL, errno); + return -1; + } + } + + return 0; +} + + +int uv_fs_unlink(uv_fs_t* req, const char* path, uv_fs_cb cb) { + uv_fs_req_init(req, UV_FS_UNLINK, cb); + + if (cb) { + /* async */ + req->eio = eio_unlink(path, EIO_PRI_DEFAULT, uv__fs_after, req); + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + + } else { + /* sync */ + req->result = unlink(path); + + if (req->result) { + uv_err_new(NULL, errno); + return -1; + } + } + + return 0; +} + + +int uv_fs_write(uv_fs_t* req, uv_file file, void* buf, size_t length, off_t offset, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_mkdir(uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_rmdir(uv_fs_t* req, const char* path, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_readdir(uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_stat(uv_fs_t* req, const char* path, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_fstat(uv_fs_t* req, uv_file file, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_rename(uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_fsync(uv_fs_t* req, uv_file file, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_fdatasync(uv_fs_t* req, uv_file file, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_ftruncate(uv_fs_t* req, uv_file file, off_t offset, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_sendfile(uv_fs_t* req, uv_file out_fd, uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_chmod(uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_utime(uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_futime(uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_lstat(uv_fs_t* req, const char* path, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_link(uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_symlink(uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_readlink(uv_fs_t* req, const char* path, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_fchmod(uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_chown(uv_fs_t* req, const char* path, int uid, int gid, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_fs_fchown(uv_fs_t* req, uv_file file, int uid, int gid, uv_fs_cb cb) { + assert(0 && "implement me"); + return -1; +} + + +int uv_queue_work(uv_work_t* req, uv_work_cb work_cb, + uv_after_work_cb after_work_cb) { + assert(0 && "implement me"); + return -1; +} diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h new file mode 100644 index 000000000..87ea7fb6b --- /dev/null +++ b/deps/uv/src/unix/internal.h @@ -0,0 +1,34 @@ +/* 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. + */ + +#ifndef UV_UNIX_INTERNAL_H_ +#define UV_UNIX_INTERNAL_H_ + +#include "uv-common.h" +#include "uv-eio.h" + +int uv__close(int fd); +void uv__req_init(uv_req_t*); +uv_err_t uv_err_new(uv_handle_t* handle, int sys_error); +int uv__nonblock(int fd, int set) __attribute__((unused)); +int uv__cloexec(int fd, int set) __attribute__((unused)); + +#endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index fbe479738..a1e74c617 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -31,6 +31,13 @@ #define COUNTOF(a) (sizeof(a) / sizeof(a[0])) +/* Used for the uv_fs_ functions */ +#define SET_REQ_RESULT(req, result) \ + req->result = result; \ + if (result == -1) { \ + req->errorno = errno; \ + } + /* * Subclass of uv_handle_t. Used for integration of c-ares. */ diff --git a/deps/uv/src/uv-unix.c b/deps/uv/src/uv-unix.c index f45aa2276..914cd15ce 100644 --- a/deps/uv/src/uv-unix.c +++ b/deps/uv/src/uv-unix.c @@ -23,8 +23,7 @@ #endif #include "uv.h" -#include "uv-common.h" -#include "uv-eio.h" +#include "unix/internal.h" #include <stddef.h> /* NULL */ #include <stdio.h> /* printf */ @@ -100,11 +99,9 @@ struct uv_ares_data_s { static struct uv_ares_data_s ares_data; -void uv__req_init(uv_req_t*); void uv__next(EV_P_ ev_idle* watcher, int revents); static int uv__stream_open(uv_stream_t*, int fd, int flags); static void uv__finish_close(uv_handle_t* handle); -static uv_err_t uv_err_new(uv_handle_t* handle, int sys_error); static int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb); static int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); @@ -141,13 +138,9 @@ static int uv__udp_send(uv_udp_send_t* req, #define __attribute__(a) #endif -/* Unused on systems that support O_CLOEXEC, SOCK_CLOEXEC, etc. */ -static int uv__cloexec(int fd, int set) __attribute__((unused)); -static int uv__nonblock(int fd, int set) __attribute__((unused)); static int uv__socket(int domain, int type, int protocol); static int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t len); -static int uv__close(int fd); size_t uv__strlcpy(char* dst, const char* src, size_t size); @@ -226,7 +219,7 @@ static uv_err_t uv_err_new_artificial(uv_handle_t* handle, int code) { } -static uv_err_t uv_err_new(uv_handle_t* handle, int sys_error) { +uv_err_t uv_err_new(uv_handle_t* handle, int sys_error) { uv_err_t err; err.sys_errno_ = sys_error; err.code = uv_translate_sys_error(sys_error); @@ -2630,7 +2623,7 @@ static int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) { } -static int uv__close(int fd) { +int uv__close(int fd) { int status; /* @@ -2647,7 +2640,7 @@ static int uv__close(int fd) { } -static int uv__nonblock(int fd, int set) { +int uv__nonblock(int fd, int set) { int flags; if ((flags = fcntl(fd, F_GETFL)) == -1) { @@ -2668,7 +2661,7 @@ static int uv__nonblock(int fd, int set) { } -static int uv__cloexec(int fd, int set) { +int uv__cloexec(int fd, int set) { int flags; if ((flags = fcntl(fd, F_GETFD)) == -1) { @@ -2961,3 +2954,4 @@ int uv_process_kill(uv_process_t* process, int signum) { return 0; } } + diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index c85952b6b..89e726fa8 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -73,6 +73,9 @@ void uv_init() { /* Fetch winapi function pointers */ uv_winapi_init(); + /* Initialize FS */ + uv_fs_init(); + /* Intialize event loop */ uv_loop_init(); } diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c new file mode 100644 index 000000000..475018427 --- /dev/null +++ b/deps/uv/src/win/fs.c @@ -0,0 +1,733 @@ +/* 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 <assert.h> +#include <malloc.h> +#include <direct.h> +#include <fcntl.h> +#include <io.h> +#include <sys/stat.h> +#include <sys/utime.h> +#include <stdio.h> + +#include "uv.h" +#include "internal.h" + +#define UV_FS_ASYNC_QUEUED 0x0001 +#define UV_FS_FREE_ARG0 0x0002 +#define UV_FS_FREE_ARG1 0x0004 +#define UV_FS_FREE_PTR 0x0008 +#define UV_FS_CLEANEDUP 0x0010 + +#define STRDUP_ARG(req, i) \ + req->arg##i = (void*)strdup((const char*)req->arg##i); \ + if (!req->arg##i) { \ + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); \ + } \ + req->flags |= UV_FS_FREE_ARG##i; + +#define WRAP_REQ_ARGS1(req, a0) \ + req->arg0 = (void*)a0; + +#define WRAP_REQ_ARGS2(req, a0, a1) \ + WRAP_REQ_ARGS1(req, a0) \ + req->arg1 = (void*)a1; + +#define WRAP_REQ_ARGS3(req, a0, a1, a2) \ + WRAP_REQ_ARGS2(req, a0, a1) \ + req->arg2 = (void*)a2; + +#define WRAP_REQ_ARGS4(req, a0, a1, a2, a3) \ + WRAP_REQ_ARGS3(req, a0, a1, a2) \ + req->arg3 = (void*)a3; + +#define QUEUE_FS_TP_JOB(req) \ + if (!QueueUserWorkItem(&uv_fs_thread_proc, req, WT_EXECUTELONGFUNCTION)) {\ + uv_set_sys_error(GetLastError()); \ + return -1; \ + } \ + req->flags |= UV_FS_ASYNC_QUEUED; \ + uv_ref(); + + +void uv_fs_init() { + _fmode = _O_BINARY; +} + + +static void uv_fs_req_init_async(uv_fs_t* req, uv_fs_type fs_type, uv_fs_cb cb) { + uv_req_init((uv_req_t*) req); + req->type = UV_FS; + req->flags = 0; + req->fs_type = fs_type; + req->cb = cb; + req->result = 0; + req->ptr = NULL; + req->errorno = 0; + memset(&req->overlapped, 0, sizeof(req->overlapped)); +} + + +static void uv_fs_req_init_sync(uv_fs_t* req, uv_fs_type fs_type) { + uv_req_init((uv_req_t*) req); + req->type = UV_FS; + req->flags = 0; + req->fs_type = fs_type; + req->result = 0; + req->ptr = NULL; + req->errorno = 0; +} + + +void fs__open(uv_fs_t* req, const char* path, int flags, int mode) { + int result = _open(path, flags, mode); + SET_REQ_RESULT(req, result); +} + + +void fs__close(uv_fs_t* req, uv_file file) { + int result = _close(file); + SET_REQ_RESULT(req, result); +} + + +void fs__read(uv_fs_t* req, uv_file file, void *buf, size_t length, off_t offset) { + int result = 0; + + if (offset != -1) { + result = _lseek(file, offset, SEEK_SET); + } + + if (result != -1) { + result = _read(file, buf, length); + } + + SET_REQ_RESULT(req, result); +} + + +void fs__write(uv_fs_t* req, uv_file file, void *buf, size_t length, off_t offset) { + int result = 0; + + if (offset != -1) { + result = _lseek(file, offset, SEEK_SET); + } + + if (result != -1) { + result = _write(file, buf, length); + } + + SET_REQ_RESULT(req, result); +} + + +void fs__unlink(uv_fs_t* req, const char* path) { + int result = _unlink(path); + SET_REQ_RESULT(req, result); +} + + +void fs__mkdir(uv_fs_t* req, const char* path, int mode) { + int result = _mkdir(path); + SET_REQ_RESULT(req, result); +} + + +void fs__rmdir(uv_fs_t* req, const char* path) { + int result = _rmdir(path); + SET_REQ_RESULT(req, result); +} + + +void fs__readdir(uv_fs_t* req, const char* path, int flags) { + int result; + char* buf, *ptr, *name; + HANDLE dir; + WIN32_FIND_DATAA ent = {0}; + size_t len = strlen(path); + size_t buf_size = 4096; + const char* fmt = !len ? "./*" + : (path[len - 1] == '/' || path[len - 1] == '\\') ? "%s*" + : "%s\\*"; + + char* path2 = (char*)malloc(len + 4); + if (!path2) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + sprintf(path2, fmt, path); + dir = FindFirstFileA(path2, &ent); + free(path2); + + if(dir == INVALID_HANDLE_VALUE) { + result = -1; + goto done; + } + + buf = (char*)malloc(buf_size); + if (!buf) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + ptr = buf; + result = 0; + + do { + name = ent.cFileName; + + if (name[0] != '.' || (name[1] && (name[1] != '.' || name[2]))) { + len = strlen(name); + + while ((ptr - buf) + len + 1 > buf_size) { + buf_size *= 2; + path2 = buf; + buf = (char*)realloc(buf, buf_size); + if (!buf) { + uv_fatal_error(ERROR_OUTOFMEMORY, "realloc"); + } + + ptr = buf + (ptr - path2); + } + + strcpy(ptr, name); + ptr += len + 1; + result++; + } + } while(FindNextFileA(dir, &ent)); + + FindClose(dir); + + req->ptr = buf; + req->flags |= UV_FS_FREE_PTR; + +done: + SET_REQ_RESULT(req, result); +} + + +void fs__stat(uv_fs_t* req, const char* path) { + int result; + + req->ptr = malloc(sizeof(struct _stat)); + if (!req->ptr) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + result = _stat(path, (struct _stat*)req->ptr); + if (result == -1) { + free(req->ptr); + req->ptr = NULL; + } else { + req->flags |= UV_FS_FREE_PTR; + } + + SET_REQ_RESULT(req, result); +} + + +void fs__fstat(uv_fs_t* req, uv_file file) { + int result; + + req->ptr = malloc(sizeof(struct _stat)); + if (!req->ptr) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + result = _fstat(file, (struct _stat*)req->ptr); + if (result == -1) { + free(req->ptr); + req->ptr = NULL; + } else { + req->flags |= UV_FS_FREE_PTR; + } + + SET_REQ_RESULT(req, result); +} + + +void fs__rename(uv_fs_t* req, const char* path, const char* new_path) { + int result = rename(path, new_path); + SET_REQ_RESULT(req, result); +} + + +void fs__fsync(uv_fs_t* req, uv_file file) { + int result = FlushFileBuffers((HANDLE)_get_osfhandle(file)) ? 0 : -1; + SET_REQ_RESULT(req, result); +} + + +void fs__ftruncate(uv_fs_t* req, uv_file file, off_t offset) { + int result = _chsize(file, offset); + SET_REQ_RESULT(req, result); +} + + +void fs__sendfile(uv_fs_t* req, uv_file out_file, uv_file in_file, off_t in_offset, size_t length) { + const size_t max_buf_size = 65536; + size_t buf_size = length < max_buf_size ? length : max_buf_size; + int n, result = 0; + char* buf = (char*)malloc(buf_size); + if (!buf) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + if (in_offset != -1) { + result = _lseek(in_file, in_offset, SEEK_SET); + } + + if (result != -1) { + while (length > 0) { + n = _read(in_file, buf, length < buf_size ? length : buf_size); + if (n == 0) { + break; + } else if (n == -1) { + result = -1; + break; + } + + length -= n; + + n = _write(out_file, buf, n); + if (n == -1) { + result = -1; + break; + } + + result += n; + } + } + + SET_REQ_RESULT(req, result); +} + + +void fs__chmod(uv_fs_t* req, const char* path, int mode) { + int result = _chmod(path, mode); + SET_REQ_RESULT(req, result); +} + + +void fs__utime(uv_fs_t* req, const char* path, double atime, double mtime) { + int result; + struct _utimbuf b = {(time_t)atime, (time_t)mtime}; + result = _utime(path, &b); + SET_REQ_RESULT(req, result); +} + + +void fs__futime(uv_fs_t* req, uv_file file, double atime, double mtime) { + int result; + struct _utimbuf b = {(time_t)atime, (time_t)mtime}; + result = _futime(file, &b); + SET_REQ_RESULT(req, result); +} + + +static DWORD WINAPI uv_fs_thread_proc(void* parameter) { + uv_fs_t* req = (uv_fs_t*)parameter; + + assert(req != NULL); + assert(req->type == UV_FS); + + switch (req->fs_type) { + case UV_FS_OPEN: + fs__open(req, (const char*)req->arg0, (int)req->arg1, (int)req->arg2); + break; + case UV_FS_CLOSE: + fs__close(req, (uv_file)req->arg0); + break; + case UV_FS_READ: + fs__read(req, (uv_file)req->arg0, req->arg1, (size_t)req->arg2, (off_t)req->arg3); + break; + case UV_FS_WRITE: + fs__write(req, (uv_file)req->arg0, req->arg1, (size_t)req->arg2, (off_t)req->arg3); + break; + case UV_FS_UNLINK: + fs__unlink(req, (const char*)req->arg0); + break; + case UV_FS_MKDIR: + fs__mkdir(req, (const char*)req->arg0, (int)req->arg1); + break; + case UV_FS_RMDIR: + fs__rmdir(req, (const char*)req->arg0); + break; + case UV_FS_READDIR: + fs__readdir(req, (const char*)req->arg0, (int)req->arg1); + break; + case UV_FS_STAT: + fs__stat(req, (const char*)req->arg0); + break; + case UV_FS_FSTAT: + fs__fstat(req, (uv_file)req->arg0); + break; + case UV_FS_RENAME: + fs__rename(req, (const char*)req->arg0, (const char*)req->arg1); + break; + case UV_FS_FSYNC: + case UV_FS_FDATASYNC: + fs__fsync(req, (uv_file)req->arg0); + break; + case UV_FS_FTRUNCATE: + fs__ftruncate(req, (uv_file)req->arg0, (off_t)req->arg1); + break; + case UV_FS_SENDFILE: + fs__sendfile(req, (uv_file)req->arg0, (uv_file)req->arg1, (off_t)req->arg2, (size_t)req->arg3); + break; + case UV_FS_CHMOD: + fs__chmod(req, (const char*)req->arg0, (int)req->arg1); + break; + case UV_FS_UTIME: + fs__utime(req, (const char*)req->arg0, req->arg4, req->arg5); + break; + case UV_FS_FUTIME: + fs__futime(req, (uv_file)req->arg0, req->arg4, req->arg5); + break; + default: + assert(!"bad uv_fs_type"); + } + + POST_COMPLETION_FOR_REQ(req); + + return 0; +} + + +int uv_fs_open(uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_OPEN, cb); + WRAP_REQ_ARGS3(req, path, flags, mode); + STRDUP_ARG(req, 0); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_OPEN); + fs__open(req, path, flags, mode); + } + + return 0; +} + + +int uv_fs_close(uv_fs_t* req, uv_file file, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_CLOSE, cb); + WRAP_REQ_ARGS1(req, file); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_CLOSE); + fs__close(req, file); + } + + return 0; +} + + +int uv_fs_read(uv_fs_t* req, uv_file file, void* buf, size_t length, off_t offset, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_READ, cb); + WRAP_REQ_ARGS4(req, file, buf, length, offset); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_READ); + fs__read(req, file, buf, length, offset); + } + + return 0; +} + + +int uv_fs_write(uv_fs_t* req, uv_file file, void* buf, size_t length, off_t offset, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_WRITE, cb); + WRAP_REQ_ARGS4(req, file, buf, length, offset); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_WRITE); + fs__write(req, file, buf, length, offset); + } + + return 0; +} + + +int uv_fs_unlink(uv_fs_t* req, const char* path, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_UNLINK, cb); + WRAP_REQ_ARGS1(req, path); + STRDUP_ARG(req, 0); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_UNLINK); + fs__unlink(req, path); + } + + return 0; +} + + +int uv_fs_mkdir(uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_MKDIR, cb); + WRAP_REQ_ARGS2(req, path, mode); + STRDUP_ARG(req, 0); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_MKDIR); + fs__mkdir(req, path, mode); + } + + return 0; +} + + +int uv_fs_rmdir(uv_fs_t* req, const char* path, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_RMDIR, cb); + WRAP_REQ_ARGS1(req, path); + STRDUP_ARG(req, 0); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_RMDIR); + fs__rmdir(req, path); + } + + return 0; +} + + +int uv_fs_readdir(uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_READDIR, cb); + WRAP_REQ_ARGS2(req, path, flags); + STRDUP_ARG(req, 0); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_READDIR); + fs__readdir(req, path, flags); + } + + return 0; +} + + +int uv_fs_stat(uv_fs_t* req, const char* path, uv_fs_cb cb) { + int len = strlen(path); + char* path2 = NULL; + int has_backslash = (path[len - 1] == '\\' || path[len - 1] == '/'); + + if (path[len - 1] == '\\' || path[len - 1] == '/') { + path2 = strdup(path); + if (!path2) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + path2[len - 1] = '\0'; + } + + if (cb) { + uv_fs_req_init_async(req, UV_FS_STAT, cb); + if (path2) { + WRAP_REQ_ARGS1(req, path2); + req->flags |= UV_FS_FREE_ARG0; + } else { + WRAP_REQ_ARGS1(req, path); + STRDUP_ARG(req, 0); + } + + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_STAT); + fs__stat(req, path2 ? path2 : path); + if (path2) { + free(path2); + } + } + + return 0; +} + + +int uv_fs_fstat(uv_fs_t* req, uv_file file, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_FSTAT, cb); + WRAP_REQ_ARGS1(req, file); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_FSTAT); + fs__fstat(req, file); + } + + return 0; +} + + +int uv_fs_rename(uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_RENAME, cb); + WRAP_REQ_ARGS2(req, path, new_path); + STRDUP_ARG(req, 0); + STRDUP_ARG(req, 1); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_RENAME); + fs__rename(req, path, new_path); + } + + return 0; +} + + +int uv_fs_fdatasync(uv_fs_t* req, uv_file file, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_FDATASYNC, cb); + WRAP_REQ_ARGS1(req, file); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_FDATASYNC); + fs__fsync(req, file); + } + + return 0; +} + + +int uv_fs_fsync(uv_fs_t* req, uv_file file, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_FSYNC, cb); + WRAP_REQ_ARGS1(req, file); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_FSYNC); + fs__fsync(req, file); + } + + return 0; +} + + +int uv_fs_ftruncate(uv_fs_t* req, uv_file file, off_t offset, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_FTRUNCATE, cb); + WRAP_REQ_ARGS2(req, file, offset); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_FTRUNCATE); + fs__ftruncate(req, file, offset); + } + + return 0; +} + + +int uv_fs_sendfile(uv_fs_t* req, uv_file out_fd, uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_SENDFILE, cb); + WRAP_REQ_ARGS4(req, out_fd, in_fd, in_offset, length); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_SENDFILE); + fs__sendfile(req, out_fd, in_fd, in_offset, length); + } + + return 0; +} + + +int uv_fs_chmod(uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_CHMOD, cb); + WRAP_REQ_ARGS2(req, path, mode); + STRDUP_ARG(req, 0); + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_CHMOD); + fs__chmod(req, path, mode); + } + + return 0; +} + + +int uv_fs_utime(uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_UTIME, cb); + WRAP_REQ_ARGS1(req, path); + STRDUP_ARG(req, 0); + req->arg4 = (ssize_t)atime; + req->arg5 = (ssize_t)mtime; + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_UTIME); + fs__utime(req, path, atime, mtime); + } + + return 0; +} + + +int uv_fs_futime(uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(req, UV_FS_FUTIME, cb); + WRAP_REQ_ARGS1(req, file); + req->arg4 = (ssize_t)atime; + req->arg5 = (ssize_t)mtime; + QUEUE_FS_TP_JOB(req); + } else { + uv_fs_req_init_sync(req, UV_FS_FUTIME); + fs__futime(req, file, atime, mtime); + } + + return 0; +} + + +void uv_process_fs_req(uv_fs_t* req) { + assert(req->cb); + req->cb(req); +} + + +void uv_fs_req_cleanup(uv_fs_t* req) { + if (req->flags & UV_FS_CLEANEDUP) { + return; + } + + if (req->flags & UV_FS_FREE_ARG0 && req->arg0) { + free(req->arg0); + req->arg0 = NULL; + } + + if (req->flags & UV_FS_FREE_ARG1 && req->arg1) { + free(req->arg1); + req->arg1 = NULL; + } + + if (req->flags & UV_FS_FREE_PTR && req->ptr) { + free(req->ptr); + req->ptr = NULL; + } + + if (req->flags & UV_FS_ASYNC_QUEUED) { + uv_unref(); + } + + req->flags |= UV_FS_CLEANEDUP; +} diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index ab203caa0..50b9368f2 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -252,6 +252,19 @@ void uv_process_getaddrinfo_req(uv_getaddrinfo_t* handle, uv_req_t* req); /* + * FS + */ +void uv_fs_init(); +void uv_process_fs_req(uv_fs_t* req); + + +/* + * Threadpool + */ +void uv_process_work_req(uv_work_t* req); + + +/* * Error handling */ extern const uv_err_t uv_ok_; diff --git a/deps/uv/src/win/req.c b/deps/uv/src/win/req.c index 5b88ff9b4..53430ec07 100644 --- a/deps/uv/src/win/req.c +++ b/deps/uv/src/win/req.c @@ -150,6 +150,14 @@ void uv_process_reqs() { uv_process_proc_close((uv_process_t*) req->data); break; + case UV_FS: + uv_process_fs_req((uv_fs_t*) req); + break; + + case UV_WORK: + uv_process_work_req((uv_work_t*) req); + break; + default: assert(0); } diff --git a/deps/uv/src/win/threadpool.c b/deps/uv/src/win/threadpool.c new file mode 100644 index 000000000..5b4436e75 --- /dev/null +++ b/deps/uv/src/win/threadpool.c @@ -0,0 +1,69 @@ +/* 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 <assert.h> + +#include "uv.h" +#include "internal.h" + + +static void uv_work_req_init(uv_work_t* req, uv_work_cb work_cb, uv_after_work_cb after_work_cb) { + uv_req_init((uv_req_t*) req); + req->type = UV_WORK; + req->work_cb = work_cb; + req->after_work_cb = after_work_cb; + memset(&req->overlapped, 0, sizeof(req->overlapped)); +} + + +static DWORD WINAPI uv_work_thread_proc(void* parameter) { + uv_work_t* req = (uv_work_t*)parameter; + + assert(req != NULL); + assert(req->type == UV_WORK); + assert(req->work_cb); + + req->work_cb(req); + + POST_COMPLETION_FOR_REQ(req); + + return 0; +} + + +int uv_queue_work(uv_work_t* req, uv_work_cb work_cb, uv_after_work_cb after_work_cb) { + uv_work_req_init(req, work_cb, after_work_cb); + + if (!QueueUserWorkItem(&uv_work_thread_proc, req, WT_EXECUTELONGFUNCTION)) { + uv_set_sys_error(GetLastError()); + return -1; + } + + uv_ref(); + return 0; +} + + +void uv_process_work_req(uv_work_t* req) { + assert(req->after_work_cb); + req->after_work_cb(req); + uv_unref(); +} diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c new file mode 100644 index 000000000..9be09e465 --- /dev/null +++ b/deps/uv/test/test-fs.c @@ -0,0 +1,541 @@ +/* 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. + */ + +/* FIXME we shouldnt need to branch in this file */ +#define UNIX (defined(__unix__) || defined(__POSIX__) || defined(__APPLE__)) + +#include "uv.h" +#include "task.h" + +#if !UNIX +# include <direct.h> +# include <io.h> +#endif + +#include <string.h> /* memset */ +#include <fcntl.h> +#include <sys/stat.h> + +static int close_cb_count; +static int create_cb_count; +static int open_cb_count; +static int read_cb_count; +static int write_cb_count; +static int unlink_cb_count; +static int mkdir_cb_count; +static int rmdir_cb_count; +static int readdir_cb_count; +static int stat_cb_count; +static int rename_cb_count; +static int fsync_cb_count; +static int fdatasync_cb_count; +static int ftruncate_cb_count; +static int sendfile_cb_count; + +static uv_fs_t open_req1; +static uv_fs_t open_req2; +static uv_fs_t read_req; +static uv_fs_t write_req; +static uv_fs_t unlink_req; +static uv_fs_t close_req; +static uv_fs_t mkdir_req; +static uv_fs_t rmdir_req; +static uv_fs_t readdir_req; +static uv_fs_t stat_req; +static uv_fs_t rename_req; +static uv_fs_t fsync_req; +static uv_fs_t fdatasync_req; +static uv_fs_t ftruncate_req; +static uv_fs_t sendfile_req; + +static char buf[32]; +static char test_buf[] = "test-buffer\n"; + + +static void unlink_cb(uv_fs_t* req) { + ASSERT(req == &unlink_req); + ASSERT(req->fs_type == UV_FS_UNLINK); + ASSERT(req->result != -1); + unlink_cb_count++; + uv_fs_req_cleanup(req); +} + + +static void close_cb(uv_fs_t* req) { + int r; + ASSERT(req == &close_req); + ASSERT(req->fs_type == UV_FS_CLOSE); + ASSERT(req->result != -1); + close_cb_count++; + uv_fs_req_cleanup(req); + if (close_cb_count == 3) { + r = uv_fs_unlink(&unlink_req, "test_file2", unlink_cb); + } +} + + +static void ftruncate_cb(uv_fs_t* req) { + int r; + ASSERT(req == &ftruncate_req); + ASSERT(req->fs_type == UV_FS_FTRUNCATE); + ASSERT(req->result != -1); + ftruncate_cb_count++; + uv_fs_req_cleanup(req); + r = uv_fs_close(&close_req, open_req1.result, close_cb); +} + + +static void read_cb(uv_fs_t* req) { + int r; + ASSERT(req == &read_req); + ASSERT(req->fs_type == UV_FS_READ); + ASSERT(req->result != -1); + read_cb_count++; + uv_fs_req_cleanup(req); + if (read_cb_count == 1) { + ASSERT(strcmp(buf, test_buf) == 0); + r = uv_fs_ftruncate(&ftruncate_req, open_req1.result, 7, ftruncate_cb); + } else { + ASSERT(strcmp(buf, "test-bu") == 0); + r = uv_fs_close(&close_req, open_req1.result, close_cb); + } +} + + +static void open_cb(uv_fs_t* req) { + int r; + ASSERT(req == &open_req1); + ASSERT(req->fs_type == UV_FS_OPEN); + ASSERT(req->result != -1); + open_cb_count++; + uv_fs_req_cleanup(req); + memset(buf, 0, sizeof(buf)); + r = uv_fs_read(&read_req, open_req1.result, buf, sizeof(buf), -1, read_cb); +} + + +static void fsync_cb(uv_fs_t* req) { + int r; + ASSERT(req == &fsync_req); + ASSERT(req->fs_type == UV_FS_FSYNC); + ASSERT(req->result != -1); + fsync_cb_count++; + uv_fs_req_cleanup(req); + r = uv_fs_close(&close_req, open_req1.result, close_cb); +} + + +static void fdatasync_cb(uv_fs_t* req) { + int r; + ASSERT(req == &fdatasync_req); + ASSERT(req->fs_type == UV_FS_FDATASYNC); + ASSERT(req->result != -1); + fdatasync_cb_count++; + uv_fs_req_cleanup(req); + r = uv_fs_fsync(&fsync_req, open_req1.result, fsync_cb); +} + + +static void write_cb(uv_fs_t* req) { + int r; + ASSERT(req == &write_req); + ASSERT(req->fs_type == UV_FS_WRITE); + ASSERT(req->result != -1); + write_cb_count++; + uv_fs_req_cleanup(req); + r = uv_fs_fdatasync(&fdatasync_req, open_req1.result, fdatasync_cb); +} + + +static void create_cb(uv_fs_t* req) { + int r; + ASSERT(req == &open_req1); + ASSERT(req->fs_type == UV_FS_OPEN); + ASSERT(req->result != -1); + create_cb_count++; + uv_fs_req_cleanup(req); + r = uv_fs_write(&write_req, req->result, test_buf, sizeof(test_buf), -1, write_cb); +} + + +static void rename_cb(uv_fs_t* req) { + ASSERT(req == &rename_req); + ASSERT(req->fs_type == UV_FS_RENAME); + ASSERT(req->result != -1); + rename_cb_count++; + uv_fs_req_cleanup(req); +} + + +static void mkdir_cb(uv_fs_t* req) { + ASSERT(req == &mkdir_req); + ASSERT(req->fs_type == UV_FS_MKDIR); + ASSERT(req->result != -1); + mkdir_cb_count++; + uv_fs_req_cleanup(req); +} + + +static void rmdir_cb(uv_fs_t* req) { + ASSERT(req == &rmdir_req); + ASSERT(req->fs_type == UV_FS_RMDIR); + ASSERT(req->result != -1); + rmdir_cb_count++; + uv_fs_req_cleanup(req); +} + + +static void readdir_cb(uv_fs_t* req) { + ASSERT(req == &readdir_req); + ASSERT(req->fs_type == UV_FS_READDIR); + ASSERT(req->result == 2); + ASSERT(req->ptr); + ASSERT(strcmp((const char*)req->ptr, "file1") == 0); + ASSERT(strcmp((char*)req->ptr + strlen((const char*)req->ptr) + 1, "file2") == 0); + readdir_cb_count++; + uv_fs_req_cleanup(req); + ASSERT(!req->ptr); +} + + +static void stat_cb(uv_fs_t* req) { + ASSERT(req == &stat_req); + ASSERT(req->fs_type == UV_FS_STAT); + ASSERT(req->result != -1); + ASSERT(req->ptr); + stat_cb_count++; + uv_fs_req_cleanup(req); + ASSERT(!req->ptr); +} + + +static void sendfile_cb(uv_fs_t* req) { + ASSERT(req == &sendfile_req); + ASSERT(req->fs_type == UV_FS_SENDFILE); + ASSERT(req->result == 65548); + sendfile_cb_count++; + uv_fs_req_cleanup(req); +} + + +TEST_IMPL(fs_file_async) { + int r; + + /* Setup. */ +#if UNIX + ASSERT(0 && "implement me"); +#else + _unlink("test_file"); + _unlink("test_file2"); +#endif + + uv_init(); + + r = uv_fs_open(&open_req1, "test_file", O_WRONLY | O_CREAT, S_IWRITE, create_cb); + ASSERT(r == 0); + uv_run(); + + ASSERT(create_cb_count == 1); + ASSERT(write_cb_count == 1); + ASSERT(fsync_cb_count == 1); + ASSERT(fdatasync_cb_count == 1); + ASSERT(close_cb_count == 1); + + r = uv_fs_rename(&rename_req, "test_file", "test_file2", rename_cb); + ASSERT(r == 0); + + uv_run(); + ASSERT(create_cb_count == 1); + ASSERT(write_cb_count == 1); + ASSERT(close_cb_count == 1); + ASSERT(rename_cb_count == 1); + + r = uv_fs_open(&open_req1, "test_file2", O_RDWR, 0, open_cb); + ASSERT(r == 0); + + uv_run(); + ASSERT(open_cb_count == 1); + ASSERT(read_cb_count == 1); + ASSERT(close_cb_count == 2); + ASSERT(rename_cb_count == 1); + ASSERT(create_cb_count == 1); + ASSERT(write_cb_count == 1); + ASSERT(ftruncate_cb_count == 1); + + r = uv_fs_open(&open_req1, "test_file2", O_RDONLY, 0, open_cb); + ASSERT(r == 0); + + uv_run(); + ASSERT(open_cb_count == 2); + ASSERT(read_cb_count == 2); + ASSERT(close_cb_count == 3); + ASSERT(rename_cb_count == 1); + ASSERT(unlink_cb_count == 1); + ASSERT(create_cb_count == 1); + ASSERT(write_cb_count == 1); + ASSERT(ftruncate_cb_count == 1); + +#if UNIX + ASSERT(0 && "implement me"); +#else + /* Cleanup. */ + _unlink("test_file"); + _unlink("test_file2"); +#endif + + return 0; +} + + +TEST_IMPL(fs_file_sync) { + int r; + +#if UNIX + ASSERT(0 && "implement me"); +#else + /* Setup. */ + _unlink("test_file"); + _unlink("test_file2"); +#endif + + uv_init(); + + r = uv_fs_open(&open_req1, "test_file", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD, NULL); + ASSERT(r == 0); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + r = uv_fs_write(&write_req, open_req1.result, test_buf, sizeof(test_buf), -1, NULL); + ASSERT(r == 0); + ASSERT(write_req.result != -1); + uv_fs_req_cleanup(&write_req); + + r = uv_fs_close(&close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result != -1); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_open(&open_req1, "test_file", O_RDWR, 0, NULL); + ASSERT(r == 0); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + r = uv_fs_read(&read_req, open_req1.result, buf, sizeof(buf), -1, NULL); + ASSERT(r == 0); + ASSERT(read_req.result != -1); + ASSERT(strcmp(buf, test_buf) == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_ftruncate(&ftruncate_req, open_req1.result, 7, NULL); + ASSERT(r == 0); + ASSERT(ftruncate_req.result != -1); + uv_fs_req_cleanup(&ftruncate_req); + + r = uv_fs_close(&close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result != -1); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_rename(&rename_req, "test_file", "test_file2", NULL); + ASSERT(r == 0); + ASSERT(rename_req.result != -1); + uv_fs_req_cleanup(&rename_req); + + r = uv_fs_open(&open_req1, "test_file2", O_RDONLY, 0, NULL); + ASSERT(r == 0); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + memset(buf, 0, sizeof(buf)); + r = uv_fs_read(&read_req, open_req1.result, buf, sizeof(buf), -1, NULL); + ASSERT(r == 0); + ASSERT(read_req.result != -1); + ASSERT(strcmp(buf, "test-bu") == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(&close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result != -1); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_unlink(&unlink_req, "test_file2", NULL); + ASSERT(r == 0); + ASSERT(unlink_req.result != -1); + uv_fs_req_cleanup(&unlink_req); + + /* Cleanup */ +#if UNIX + ASSERT(0 && "implement me"); +#else + _unlink("test_file"); + _unlink("test_file2"); +#endif + + return 0; +} + + +TEST_IMPL(fs_async_dir) { + int r; + + /* Setup */ +#if UNIX + ASSERT(0 && "implement me"); +#else + _unlink("test_dir/file1"); + _unlink("test_dir/file2"); + _rmdir("test_dir"); +#endif + + uv_init(); + + r = uv_fs_mkdir(&mkdir_req, "test_dir", 0, mkdir_cb); + ASSERT(r == 0); + + uv_run(); + ASSERT(mkdir_cb_count == 1); + + /* Create 2 files synchronously. */ + r = uv_fs_open(&open_req1, "test_dir/file1", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&open_req1); + r = uv_fs_close(&close_req, open_req1.result, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_open(&open_req1, "test_dir/file2", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&open_req1); + r = uv_fs_close(&close_req, open_req1.result, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_readdir(&readdir_req, "test_dir", 0, readdir_cb); + ASSERT(r == 0); + + uv_run(); + ASSERT(readdir_cb_count == 1); + + r = uv_fs_stat(&stat_req, "test_dir", stat_cb); + ASSERT(r == 0); + uv_run(); + r = uv_fs_stat(&stat_req, "test_dir\\", stat_cb); + ASSERT(r == 0); + uv_run(); + + ASSERT(stat_cb_count == 2); + + r = uv_fs_unlink(&unlink_req, "test_dir/file1", unlink_cb); + ASSERT(r == 0); + uv_run(); + ASSERT(unlink_cb_count == 1); + + r = uv_fs_unlink(&unlink_req, "test_dir/file2", unlink_cb); + ASSERT(r == 0); + uv_run(); + ASSERT(unlink_cb_count == 2); + + r = uv_fs_rmdir(&rmdir_req, "test_dir", rmdir_cb); + ASSERT(r == 0); + uv_run(); + ASSERT(rmdir_cb_count == 1); + + /* Cleanup */ +#if UNIX + ASSERT(0 && "implement me"); +#else + _unlink("test_dir/file1"); + _unlink("test_dir/file2"); + _rmdir("test_dir"); +#endif + + return 0; +} + + +TEST_IMPL(fs_async_sendfile) { + int f, r; + + /* Setup. */ +#if UNIX + ASSERT(0 && "implement me"); +#else + struct _stat s1, s2; + + _unlink("test_file"); + _unlink("test_file2"); + + f = _open("test_file", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD); + ASSERT(f != -1); + + r = _write(f, "begin\n", 6); + ASSERT(r != -1); + + r = _lseek(f, 65536, SEEK_CUR); + ASSERT(r == 65543); + + r = _write(f, "end\n", 4); + ASSERT(r != -1); + + r = _close(f); + ASSERT(r == 0); +#endif + + /* Test starts here. */ + uv_init(); + + r = uv_fs_open(&open_req1, "test_file", O_RDWR, 0, NULL); + ASSERT(r == 0); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + r = uv_fs_open(&open_req2, "test_file2", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD, NULL); + ASSERT(r == 0); + ASSERT(open_req2.result != -1); + uv_fs_req_cleanup(&open_req2); + + r = uv_fs_sendfile(&sendfile_req, open_req2.result, open_req1.result, 0, 131072, sendfile_cb); + ASSERT(r == 0); + uv_run(); + + ASSERT(sendfile_cb_count == 1); + + r = uv_fs_close(&close_req, open_req1.result, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&close_req); + r = uv_fs_close(&close_req, open_req2.result, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&close_req); + +#if UNIX + ASSERT(0 && "implement me"); +#else + _stat("test_file", &s1); + _stat("test_file2", &s2); + ASSERT(65548 == s2.st_size && s1.st_size == s2.st_size); + + /* Cleanup. */ + _unlink("test_file"); + _unlink("test_file2"); +#endif + + return 0; +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index eeda7f40f..a16255199 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -72,6 +72,11 @@ TEST_DECLARE (spawn_exit_code) TEST_DECLARE (spawn_stdout) TEST_DECLARE (spawn_stdin) TEST_DECLARE (spawn_and_kill) +TEST_DECLARE (fs_file_async) +TEST_DECLARE (fs_file_sync) +TEST_DECLARE (fs_async_dir) +TEST_DECLARE (fs_async_sendfile) +TEST_DECLARE (threadpool_queue_work_simple) #ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) TEST_DECLARE (argument_escaping) @@ -170,6 +175,13 @@ TASK_LIST_START TEST_ENTRY (environment_creation) #endif + TEST_ENTRY (fs_file_async) + TEST_ENTRY (fs_file_sync) + TEST_ENTRY (fs_async_dir) + TEST_ENTRY (fs_async_sendfile) + + TEST_ENTRY (threadpool_queue_work_simple) + #if 0 /* These are for testing the test runner. */ TEST_ENTRY (fail_always) diff --git a/deps/uv/test/test-threadpool.c b/deps/uv/test/test-threadpool.c new file mode 100644 index 000000000..19742f238 --- /dev/null +++ b/deps/uv/test/test-threadpool.c @@ -0,0 +1,59 @@ +/* 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 "task.h" + +static int work_cb_count; +static int after_work_cb_count; +static uv_work_t work_req; +static char data; + + +static void work_cb(uv_work_t* req) { + ASSERT(req == &work_req); + ASSERT(req->data == &data); + work_cb_count++; +} + + +static void after_work_cb(uv_work_t* req) { + ASSERT(req == &work_req); + ASSERT(req->data == &data); + after_work_cb_count++; +} + + +TEST_IMPL(threadpool_queue_work_simple) { + int r; + + uv_init(); + + work_req.data = &data; + r = uv_queue_work(&work_req, work_cb, after_work_cb); + ASSERT(r == 0); + uv_run(); + + ASSERT(work_cb_count == 1); + ASSERT(after_work_cb_count == 1); + + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index ca90b826c..ab93f1d97 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -3,7 +3,10 @@ { 'target_name': 'uv', 'type': '<(library)', - 'include_dirs': [ 'include' ], + 'include_dirs': [ + 'include', + 'src/', + ], 'direct_dependent_settings': { 'include_dirs': [ 'include' ], }, @@ -98,6 +101,7 @@ 'src/win/cares.c', 'src/win/core.c', 'src/win/error.c', + 'src/win/fs.c', 'src/win/getaddrinfo.c', 'src/win/handle.c', 'src/win/internal.h', @@ -108,6 +112,7 @@ 'src/win/stdio.c', 'src/win/stream.c', 'src/win/tcp.c', + 'src/win/threadpool.c', 'src/win/timer.c', 'src/win/udp.c', 'src/win/util.c', @@ -138,6 +143,16 @@ 'src/uv-eio.c', 'src/uv-eio.h', 'src/uv-unix.c', + 'src/unix/fs.c', + 'src/unix/internal.h', + 'src/eio/ecb.h', + 'src/eio/eio.c', + 'src/eio/xthread.h', + 'src/ev/ev.c', + 'src/ev/ev_vars.h', + 'src/ev/ev_wrap.h', + 'src/ev/event.h', + # TODO: conditionally include the following based on OS? 'src/ares/config_cygwin/ares_config.h', 'src/ares/config_darwin/ares_config.h', 'src/ares/config_freebsd/ares_config.h', @@ -149,22 +164,13 @@ 'src/eio/config_freebsd.h', 'src/eio/config_linux.h', 'src/eio/config_sunos.h', - 'src/eio/ecb.h', - 'src/eio/eio.c', - 'src/eio/xthread.h', 'src/ev/config_cygwin.h', 'src/ev/config_darwin.h', 'src/ev/config_freebsd.h', 'src/ev/config_linux.h', 'src/ev/config_sunos.h', - 'src/ev/ev.c', - 'src/ev/ev_vars.h', - 'src/ev/ev_wrap.h', - 'src/ev/event.h', - ], - 'include_dirs': [ - 'src/ev' ], + 'include_dirs': [ 'src/ev', ], 'defines': [ '_LARGEFILE_SOURCE', '_FILE_OFFSET_BITS=64', @@ -214,6 +220,7 @@ 'test/test-connection-fail.c', 'test/test-delayed-accept.c', 'test/test-fail-always.c', + 'test/test-fs.c', 'test/test-get-currentexe.c', 'test/test-getaddrinfo.c', 'test/test-gethostbyname.c', @@ -231,6 +238,7 @@ 'test/test-tcp-bind-error.c', 'test/test-tcp-bind6-error.c', 'test/test-tcp-writealot.c', + 'test/test-threadpool.c', 'test/test-timer-again.c', 'test/test-timer.c', 'test/test-udp-dgram-too-big.c', |