asyncengine 0.0.1.testing1 → 0.0.2.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (251) hide show
  1. data/README.markdown +3 -0
  2. data/Rakefile +38 -0
  3. data/asyncengine.gemspec +8 -4
  4. data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
  5. data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
  6. data/ext/asyncengine/ae_handle_common.c +193 -48
  7. data/ext/asyncengine/ae_handle_common.h +40 -13
  8. data/ext/asyncengine/ae_ip_utils.c +246 -0
  9. data/ext/asyncengine/ae_ip_utils.h +25 -0
  10. data/ext/asyncengine/ae_next_tick.c +81 -21
  11. data/ext/asyncengine/ae_next_tick.h +4 -2
  12. data/ext/asyncengine/ae_resolver.c +156 -0
  13. data/ext/asyncengine/ae_resolver.h +10 -0
  14. data/ext/asyncengine/ae_tcp.c +908 -0
  15. data/ext/asyncengine/ae_tcp.h +20 -0
  16. data/ext/asyncengine/ae_timer.c +355 -81
  17. data/ext/asyncengine/ae_timer.h +11 -4
  18. data/ext/asyncengine/ae_udp.c +579 -13
  19. data/ext/asyncengine/ae_udp.h +15 -2
  20. data/ext/asyncengine/ae_utils.c +192 -0
  21. data/ext/asyncengine/ae_utils.h +16 -0
  22. data/ext/asyncengine/asyncengine_ruby.c +469 -26
  23. data/ext/asyncengine/asyncengine_ruby.h +49 -11
  24. data/ext/asyncengine/debug.h +68 -0
  25. data/ext/asyncengine/extconf.rb +26 -2
  26. data/ext/asyncengine/ip_parser.c +5954 -0
  27. data/ext/asyncengine/ip_parser.h +16 -0
  28. data/ext/asyncengine/libuv/AUTHORS +16 -0
  29. data/ext/asyncengine/libuv/common.gypi +4 -4
  30. data/ext/asyncengine/libuv/config-mingw.mk +6 -6
  31. data/ext/asyncengine/libuv/config-unix.mk +13 -13
  32. data/ext/asyncengine/libuv/gyp_uv +5 -1
  33. data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
  34. data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
  35. data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
  36. data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
  37. data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
  38. data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
  39. data/ext/asyncengine/libuv/include/uv.h +353 -88
  40. data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
  41. data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
  42. data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
  43. data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
  44. data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
  45. data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
  46. data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
  47. data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
  48. data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
  49. data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
  50. data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
  51. data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
  52. data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
  53. data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
  54. data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
  55. data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
  56. data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
  57. data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
  58. data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
  59. data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
  60. data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
  61. data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
  62. data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
  63. data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
  64. data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
  65. data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
  66. data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
  67. data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
  68. data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
  69. data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
  70. data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
  71. data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
  72. data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
  73. data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
  74. data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
  75. data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
  76. data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
  77. data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
  78. data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
  79. data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
  80. data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
  81. data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
  82. data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
  83. data/ext/asyncengine/libuv/src/cares.c +225 -0
  84. data/ext/asyncengine/libuv/src/cares.o +0 -0
  85. data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
  86. data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
  87. data/ext/asyncengine/libuv/src/unix/async.c +78 -17
  88. data/ext/asyncengine/libuv/src/unix/async.o +0 -0
  89. data/ext/asyncengine/libuv/src/unix/core.c +305 -213
  90. data/ext/asyncengine/libuv/src/unix/core.o +0 -0
  91. data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
  92. data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
  93. data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
  94. data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
  95. data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
  96. data/ext/asyncengine/libuv/src/unix/error.c +6 -0
  97. data/ext/asyncengine/libuv/src/unix/error.o +0 -0
  98. data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
  99. data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
  100. data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
  101. data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
  102. data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
  103. data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
  104. data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
  105. data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
  106. data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
  107. data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
  108. data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
  109. data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
  110. data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
  111. data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
  112. data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
  113. data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
  114. data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
  115. data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
  116. data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
  117. data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
  118. data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
  119. data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
  120. data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
  121. data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
  122. data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
  123. data/ext/asyncengine/libuv/src/unix/process.c +193 -115
  124. data/ext/asyncengine/libuv/src/unix/process.o +0 -0
  125. data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
  126. data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
  127. data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
  128. data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
  129. data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
  130. data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
  131. data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
  132. data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
  133. data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
  134. data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
  135. data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
  136. data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
  137. data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
  138. data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
  139. data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
  140. data/ext/asyncengine/libuv/src/uv-common.c +68 -38
  141. data/ext/asyncengine/libuv/src/uv-common.h +104 -20
  142. data/ext/asyncengine/libuv/src/uv-common.o +0 -0
  143. data/ext/asyncengine/libuv/src/win/async.c +20 -17
  144. data/ext/asyncengine/libuv/src/win/core.c +44 -31
  145. data/ext/asyncengine/libuv/src/win/dl.c +40 -36
  146. data/ext/asyncengine/libuv/src/win/error.c +21 -1
  147. data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
  148. data/ext/asyncengine/libuv/src/win/fs.c +541 -189
  149. data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
  150. data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
  151. data/ext/asyncengine/libuv/src/win/handle.c +26 -101
  152. data/ext/asyncengine/libuv/src/win/internal.h +92 -107
  153. data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
  154. data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
  155. data/ext/asyncengine/libuv/src/win/poll.c +618 -0
  156. data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
  157. data/ext/asyncengine/libuv/src/win/process.c +147 -274
  158. data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
  159. data/ext/asyncengine/libuv/src/win/req.c +0 -149
  160. data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
  161. data/ext/asyncengine/libuv/src/win/stream.c +9 -43
  162. data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
  163. data/ext/asyncengine/libuv/src/win/thread.c +42 -2
  164. data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
  165. data/ext/asyncengine/libuv/src/win/timer.c +13 -63
  166. data/ext/asyncengine/libuv/src/win/tty.c +26 -20
  167. data/ext/asyncengine/libuv/src/win/udp.c +26 -17
  168. data/ext/asyncengine/libuv/src/win/util.c +312 -167
  169. data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
  170. data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
  171. data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
  172. data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
  173. data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
  174. data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
  175. data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
  176. data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
  177. data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
  178. data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
  179. data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
  180. data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
  181. data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
  182. data/ext/asyncengine/libuv/test/echo-server.c +8 -0
  183. data/ext/asyncengine/libuv/test/run-tests.c +30 -0
  184. data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
  185. data/ext/asyncengine/libuv/test/runner-win.c +5 -63
  186. data/ext/asyncengine/libuv/test/runner.c +10 -1
  187. data/ext/asyncengine/libuv/test/task.h +0 -8
  188. data/ext/asyncengine/libuv/test/test-async.c +43 -141
  189. data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
  190. data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
  191. data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
  192. data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
  193. data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
  194. data/ext/asyncengine/libuv/test/test-fs.c +114 -2
  195. data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
  196. data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
  197. data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
  198. data/ext/asyncengine/libuv/test/test-list.h +59 -9
  199. data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
  200. data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
  201. data/ext/asyncengine/libuv/test/test-poll.c +573 -0
  202. data/ext/asyncengine/libuv/test/test-ref.c +79 -63
  203. data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
  204. data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
  205. data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
  206. data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
  207. data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
  208. data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
  209. data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  210. data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
  211. data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  212. data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
  213. data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
  214. data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
  215. data/ext/asyncengine/libuv/test/test-timer.c +23 -1
  216. data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
  217. data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
  218. data/ext/asyncengine/libuv/uv.gyp +26 -9
  219. data/ext/asyncengine/rb_utilities.c +54 -0
  220. data/ext/asyncengine/rb_utilities.h +63 -0
  221. data/lib/asyncengine.rb +45 -38
  222. data/lib/asyncengine/asyncengine_ext.so +0 -0
  223. data/lib/asyncengine/debug.rb +37 -0
  224. data/lib/asyncengine/handle.rb +9 -0
  225. data/lib/asyncengine/tcp.rb +28 -0
  226. data/lib/asyncengine/timer.rb +18 -28
  227. data/lib/asyncengine/udp.rb +29 -0
  228. data/lib/asyncengine/utils.rb +32 -0
  229. data/lib/asyncengine/uv_error.rb +17 -0
  230. data/lib/asyncengine/version.rb +9 -1
  231. data/test/ae_test_helper.rb +62 -0
  232. data/test/test_basic.rb +169 -0
  233. data/test/test_call_from_other_thread.rb +55 -0
  234. data/test/test_error.rb +92 -0
  235. data/test/test_ip_utils.rb +44 -0
  236. data/test/test_next_tick.rb +37 -0
  237. data/test/test_resolver.rb +51 -0
  238. data/test/test_threads.rb +69 -0
  239. data/test/test_timer.rb +95 -0
  240. data/test/test_udp.rb +216 -0
  241. data/test/test_utils.rb +49 -0
  242. metadata +84 -57
  243. data/ext/asyncengine/libuv/mkmf.log +0 -24
  244. data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
  245. data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
  246. data/ext/asyncengine/libuv/src/unix/check.o +0 -0
  247. data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
  248. data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
  249. data/ext/asyncengine/libuv/src/win/cares.c +0 -290
  250. data/lib/asyncengine/errors.rb +0 -5
  251. data/lib/asyncengine/next_tick.rb +0 -24
@@ -0,0 +1,225 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include "uv.h"
23
+ #include "tree.h"
24
+ #include "uv-common.h"
25
+
26
+ #include <assert.h>
27
+ #include <errno.h>
28
+ #include <stdlib.h>
29
+ #include <string.h>
30
+
31
+
32
+ struct uv_ares_task_s {
33
+ UV_HANDLE_FIELDS
34
+ ares_socket_t sock;
35
+ uv_poll_t poll_watcher;
36
+ RB_ENTRY(uv_ares_task_s) node;
37
+ };
38
+
39
+
40
+ static int cmp_ares_tasks(const uv_ares_task_t* a, const uv_ares_task_t* b) {
41
+ if (a->sock < b->sock) return -1;
42
+ if (a->sock > b->sock) return 1;
43
+ return 0;
44
+ }
45
+
46
+
47
+ RB_GENERATE_STATIC(uv__ares_tasks, uv_ares_task_s, node, cmp_ares_tasks)
48
+
49
+
50
+ /* Add ares handle to list. */
51
+ static void uv_add_ares_handle(uv_loop_t* loop, uv_ares_task_t* handle) {
52
+ assert(loop == handle->loop);
53
+ RB_INSERT(uv__ares_tasks, &loop->ares_handles, handle);
54
+ }
55
+
56
+
57
+ /* Find matching ares handle in list. */
58
+ static uv_ares_task_t* uv_find_ares_handle(uv_loop_t* loop, ares_socket_t sock) {
59
+ uv_ares_task_t handle;
60
+ handle.sock = sock;
61
+ return RB_FIND(uv__ares_tasks, &loop->ares_handles, &handle);
62
+ }
63
+
64
+
65
+ /* Remove ares handle from list. */
66
+ static void uv_remove_ares_handle(uv_ares_task_t* handle) {
67
+ RB_REMOVE(uv__ares_tasks, &handle->loop->ares_handles, handle);
68
+ }
69
+
70
+
71
+ /* Returns 1 if the ares_handles list is empty, 0 otherwise. */
72
+ static int uv_ares_handles_empty(uv_loop_t* loop) {
73
+ return RB_EMPTY(&loop->ares_handles);
74
+ }
75
+
76
+
77
+ /* This is called once per second by loop->timer. It is used to constantly */
78
+ /* call back into c-ares for possibly processing timeouts. */
79
+ static void uv__ares_timeout(uv_timer_t* handle, int status) {
80
+ assert(!uv_ares_handles_empty(handle->loop));
81
+ ares_process_fd(handle->loop->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
82
+ }
83
+
84
+
85
+ static void uv__ares_poll_cb(uv_poll_t* watcher, int status, int events) {
86
+ uv_loop_t* loop = watcher->loop;
87
+ uv_ares_task_t* task = container_of(watcher, uv_ares_task_t, poll_watcher);
88
+
89
+ /* Reset the idle timer */
90
+ uv_timer_again(&loop->ares_timer);
91
+
92
+ if (status < 0) {
93
+ /* An error happened. Just pretend that the socket is both readable and */
94
+ /* writable. */
95
+ ares_process_fd(loop->channel, task->sock, task->sock);
96
+ return;
97
+ }
98
+
99
+ /* Process DNS responses */
100
+ ares_process_fd(loop->channel,
101
+ events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
102
+ events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
103
+ }
104
+
105
+
106
+ static void uv__ares_poll_close_cb(uv_handle_t* watcher) {
107
+ uv_ares_task_t* task = container_of(watcher, uv_ares_task_t, poll_watcher);
108
+ free(task);
109
+ }
110
+
111
+
112
+ /* Allocates and returns a new uv_ares_task_t */
113
+ static uv_ares_task_t* uv__ares_task_create(uv_loop_t* loop, ares_socket_t sock) {
114
+ uv_ares_task_t* task = (uv_ares_task_t*) malloc(sizeof *task);
115
+
116
+ if (task == NULL) {
117
+ /* Out of memory. */
118
+ return NULL;
119
+ }
120
+
121
+ task->loop = loop;
122
+ task->sock = sock;
123
+
124
+ if (uv_poll_init_socket(loop, &task->poll_watcher, sock) < 0) {
125
+ /* This should never happen. */
126
+ free(task);
127
+ return NULL;
128
+ }
129
+
130
+ return task;
131
+ }
132
+
133
+
134
+ /* Callback from ares when socket operation is started */
135
+ static void uv__ares_sockstate_cb(void* data, ares_socket_t sock,
136
+ int read, int write) {
137
+ uv_loop_t* loop = (uv_loop_t*) data;
138
+ uv_ares_task_t* task;
139
+
140
+ task = uv_find_ares_handle(loop, sock);
141
+
142
+ if (read || write) {
143
+ if (!task) {
144
+ /* New socket */
145
+
146
+ /* If this is the first socket then start the timer. */
147
+ if (!uv_is_active((uv_handle_t*) &loop->ares_timer)) {
148
+ assert(uv_ares_handles_empty(loop));
149
+ uv_timer_start(&loop->ares_timer, uv__ares_timeout, 1000, 1000);
150
+ }
151
+
152
+ task = uv__ares_task_create(loop, sock);
153
+ if (task == NULL) {
154
+ /* This should never happen unless we're out of memory or something */
155
+ /* is seriously wrong. The socket won't be polled, but the the query */
156
+ /* will eventually time out. */
157
+ return;
158
+ }
159
+
160
+ uv_add_ares_handle(loop, task);
161
+ }
162
+
163
+ /* This should never fail. If it fails anyway, the query will eventually */
164
+ /* time out. */
165
+ uv_poll_start(&task->poll_watcher,
166
+ (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
167
+ uv__ares_poll_cb);
168
+
169
+ } else {
170
+ /* read == 0 and write == 0 this is c-ares's way of notifying us that */
171
+ /* the socket is now closed. We must free the data associated with */
172
+ /* socket. */
173
+ assert(task &&
174
+ "When an ares socket is closed we should have a handle for it");
175
+
176
+ uv_remove_ares_handle(task);
177
+ uv_close((uv_handle_t*) &task->poll_watcher, uv__ares_poll_close_cb);
178
+
179
+ if (uv_ares_handles_empty(loop)) {
180
+ uv_timer_stop(&loop->ares_timer);
181
+ }
182
+ }
183
+ }
184
+
185
+
186
+ /* C-ares integration initialize and terminate */
187
+ int uv_ares_init_options(uv_loop_t* loop, ares_channel *channelptr,
188
+ struct ares_options *options, int optmask) {
189
+ int rc;
190
+
191
+ /* only allow single init at a time */
192
+ if (loop->channel != NULL) {
193
+ uv__set_artificial_error(loop, UV_EALREADY);
194
+ return -1;
195
+ }
196
+
197
+ /* set our callback as an option */
198
+ options->sock_state_cb = uv__ares_sockstate_cb;
199
+ options->sock_state_cb_data = loop;
200
+ optmask |= ARES_OPT_SOCK_STATE_CB;
201
+
202
+ /* We do the call to ares_init_option for caller. */
203
+ rc = ares_init_options(channelptr, options, optmask);
204
+
205
+ /* if success, save channel */
206
+ if (rc == ARES_SUCCESS) {
207
+ loop->channel = *channelptr;
208
+ }
209
+
210
+ /* Initialize the timeout timer. The timer won't be started until the */
211
+ /* first socket is opened. */
212
+ uv_timer_init(loop, &loop->ares_timer);
213
+
214
+ return rc;
215
+ }
216
+
217
+
218
+ void uv_ares_destroy(uv_loop_t* loop, ares_channel channel) {
219
+ /* Only allow destroy if did init. */
220
+ if (loop->channel) {
221
+ uv_timer_stop(&loop->ares_timer);
222
+ ares_destroy(channel);
223
+ loop->channel = NULL;
224
+ }
225
+ }
@@ -0,0 +1,237 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include "uv.h"
23
+ #include "uv-common.h"
24
+
25
+ #include <assert.h>
26
+ #include <stdlib.h>
27
+ #include <string.h>
28
+
29
+ static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b);
30
+ static void timer_cb(uv_timer_t* timer, int status);
31
+ static void poll_cb(uv_fs_t* req);
32
+
33
+ static uv_statbuf_t zero_statbuf;
34
+
35
+
36
+ int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
37
+ /* TODO(bnoordhuis) Mark fs_req internal. */
38
+ uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
39
+ loop->counters.fs_poll_init++;
40
+
41
+ if (uv_timer_init(loop, &handle->timer_handle))
42
+ return -1;
43
+
44
+ handle->timer_handle.flags |= UV__HANDLE_INTERNAL;
45
+ uv__handle_unref(&handle->timer_handle);
46
+
47
+ return 0;
48
+ }
49
+
50
+
51
+ int uv_fs_poll_start(uv_fs_poll_t* handle,
52
+ uv_fs_poll_cb cb,
53
+ const char* path,
54
+ unsigned int interval) {
55
+ uv_fs_t* req;
56
+ size_t len;
57
+
58
+ if (uv__is_active(handle))
59
+ return 0;
60
+
61
+ len = strlen(path) + 1;
62
+ req = malloc(sizeof(*req) + len);
63
+
64
+ if (req == NULL)
65
+ return uv__set_artificial_error(handle->loop, UV_ENOMEM);
66
+
67
+ req->data = handle;
68
+ handle->path = memcpy(req + 1, path, len);
69
+ handle->fs_req = req;
70
+ handle->poll_cb = cb;
71
+ handle->interval = interval ? interval : 1;
72
+ handle->start_time = uv_now(handle->loop);
73
+ handle->busy_polling = 0;
74
+ memset(&handle->statbuf, 0, sizeof(handle->statbuf));
75
+
76
+ if (uv_fs_stat(handle->loop, handle->fs_req, handle->path, poll_cb))
77
+ abort();
78
+
79
+ uv__handle_start(handle);
80
+
81
+ return 0;
82
+ }
83
+
84
+
85
+ int uv_fs_poll_stop(uv_fs_poll_t* handle) {
86
+ if (!uv__is_active(handle))
87
+ return 0;
88
+
89
+ /* Don't free the fs req if it's active. Signal poll_cb that it needs to free
90
+ * the req by removing the handle backlink.
91
+ *
92
+ * TODO(bnoordhuis) Have uv-unix postpone the close callback until the req
93
+ * finishes so we don't need this pointer / lifecycle hackery. The callback
94
+ * always runs on the next tick now.
95
+ */
96
+ if (handle->fs_req->data)
97
+ handle->fs_req->data = NULL;
98
+ else
99
+ free(handle->fs_req);
100
+
101
+ handle->fs_req = NULL;
102
+ handle->path = NULL;
103
+
104
+ uv_timer_stop(&handle->timer_handle);
105
+ uv__handle_stop(handle);
106
+
107
+ return 0;
108
+ }
109
+
110
+
111
+ void uv__fs_poll_close(uv_fs_poll_t* handle) {
112
+ uv_fs_poll_stop(handle);
113
+ uv_close((uv_handle_t*)&handle->timer_handle, NULL);
114
+ }
115
+
116
+
117
+ static void timer_cb(uv_timer_t* timer, int status) {
118
+ uv_fs_poll_t* handle;
119
+
120
+ handle = container_of(timer, uv_fs_poll_t, timer_handle);
121
+ handle->start_time = uv_now(handle->loop);
122
+ handle->fs_req->data = handle;
123
+
124
+ if (uv_fs_stat(handle->loop, handle->fs_req, handle->path, poll_cb))
125
+ abort();
126
+
127
+ assert(uv__is_active(handle));
128
+ }
129
+
130
+
131
+ static void poll_cb(uv_fs_t* req) {
132
+ uv_statbuf_t* statbuf;
133
+ uv_fs_poll_t* handle;
134
+ uint64_t interval;
135
+
136
+ handle = req->data;
137
+
138
+ if (handle == NULL) /* Handle has been stopped or closed. */
139
+ goto out;
140
+
141
+ assert(req == handle->fs_req);
142
+
143
+ if (req->result != 0) {
144
+ if (handle->busy_polling != -req->errorno) {
145
+ uv__set_artificial_error(handle->loop, req->errorno);
146
+ handle->poll_cb(handle, -1, &handle->statbuf, &zero_statbuf);
147
+ handle->busy_polling = -req->errorno;
148
+ }
149
+ goto out;
150
+ }
151
+
152
+ statbuf = req->ptr;
153
+
154
+ if (handle->busy_polling != 0)
155
+ if (handle->busy_polling < 0 || !statbuf_eq(&handle->statbuf, statbuf))
156
+ handle->poll_cb(handle, 0, &handle->statbuf, statbuf);
157
+
158
+ handle->statbuf = *statbuf;
159
+ handle->busy_polling = 1;
160
+
161
+ out:
162
+ uv_fs_req_cleanup(req);
163
+
164
+ if (req->data == NULL) { /* Handle has been stopped or closed. */
165
+ free(req);
166
+ return;
167
+ }
168
+
169
+ req->data = NULL; /* Tell uv_fs_poll_stop() it's safe to free the req. */
170
+
171
+ /* Reschedule timer, subtract the delay from doing the stat(). */
172
+ interval = handle->interval;
173
+ interval -= (uv_now(handle->loop) - handle->start_time) % interval;
174
+
175
+ if (uv_timer_start(&handle->timer_handle, timer_cb, interval, 0))
176
+ abort();
177
+ }
178
+
179
+
180
+ static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b) {
181
+ #ifdef _WIN32
182
+ return a->st_mtime == b->st_mtime
183
+ && a->st_size == b->st_size
184
+ && a->st_mode == b->st_mode;
185
+ #else
186
+
187
+ /* Jump through a few hoops to get sub-second granularity on Linux. */
188
+ # if __linux__
189
+ # if __USE_MISC /* _BSD_SOURCE || _SVID_SOURCE */
190
+ if (a->st_ctim.tv_nsec != b->st_ctim.tv_nsec) return 0;
191
+ if (a->st_mtim.tv_nsec != b->st_mtim.tv_nsec) return 0;
192
+ # else
193
+ if (a->st_ctimensec != b->st_ctimensec) return 0;
194
+ if (a->st_mtimensec != b->st_mtimensec) return 0;
195
+ # endif
196
+ # endif
197
+
198
+ /* Jump through different hoops on OS X. */
199
+ # if __APPLE__
200
+ # if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
201
+ if (a->st_ctimespec.tv_nsec != b->st_ctimespec.tv_nsec) return 0;
202
+ if (a->st_mtimespec.tv_nsec != b->st_mtimespec.tv_nsec) return 0;
203
+ # else
204
+ if (a->st_ctimensec != b->st_ctimensec) return 0;
205
+ if (a->st_mtimensec != b->st_mtimensec) return 0;
206
+ # endif
207
+ # endif
208
+
209
+ /* TODO(bnoordhuis) Other Unices have st_ctim and friends too, provided
210
+ * the stars and compiler flags are right...
211
+ */
212
+
213
+ return a->st_ctime == b->st_ctime
214
+ && a->st_mtime == b->st_mtime
215
+ && a->st_size == b->st_size
216
+ && a->st_mode == b->st_mode
217
+ && a->st_uid == b->st_uid
218
+ && a->st_gid == b->st_gid
219
+ && a->st_ino == b->st_ino
220
+ && a->st_dev == b->st_dev;
221
+ #endif
222
+ }
223
+
224
+
225
+ #ifdef _WIN32
226
+
227
+ #include "win/internal.h"
228
+ #include "win/handle-inl.h"
229
+
230
+ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) {
231
+ assert(handle->flags & UV_HANDLE_CLOSING);
232
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
233
+ uv__handle_stop(handle);
234
+ uv__handle_close(handle);
235
+ }
236
+
237
+ #endif /* _WIN32 */