noderb 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. data/LICENSE +19 -0
  2. data/README.md +25 -0
  3. data/ext/noderb_extension/extconf.rb +11 -0
  4. data/ext/noderb_extension/libuv/AUTHORS +11 -0
  5. data/ext/noderb_extension/libuv/LICENSE +48 -0
  6. data/ext/noderb_extension/libuv/Makefile +119 -0
  7. data/ext/noderb_extension/libuv/README +45 -0
  8. data/ext/noderb_extension/libuv/build/all.gyp +254 -0
  9. data/ext/noderb_extension/libuv/build/common.gypi +13 -0
  10. data/ext/noderb_extension/libuv/build/gyp_uv +43 -0
  11. data/ext/noderb_extension/libuv/config-mingw.mk +67 -0
  12. data/ext/noderb_extension/libuv/config-unix.mk +121 -0
  13. data/ext/noderb_extension/libuv/create-msvs-files.bat +14 -0
  14. data/ext/noderb_extension/libuv/deps/pthread-win32/ANNOUNCE +482 -0
  15. data/ext/noderb_extension/libuv/deps/pthread-win32/BUGS +141 -0
  16. data/ext/noderb_extension/libuv/deps/pthread-win32/Bmakefile +268 -0
  17. data/ext/noderb_extension/libuv/deps/pthread-win32/CONTRIBUTORS +140 -0
  18. data/ext/noderb_extension/libuv/deps/pthread-win32/COPYING +150 -0
  19. data/ext/noderb_extension/libuv/deps/pthread-win32/COPYING.LIB +504 -0
  20. data/ext/noderb_extension/libuv/deps/pthread-win32/ChangeLog +5194 -0
  21. data/ext/noderb_extension/libuv/deps/pthread-win32/FAQ +451 -0
  22. data/ext/noderb_extension/libuv/deps/pthread-win32/GNUmakefile +593 -0
  23. data/ext/noderb_extension/libuv/deps/pthread-win32/MAINTAINERS +4 -0
  24. data/ext/noderb_extension/libuv/deps/pthread-win32/Makefile +516 -0
  25. data/ext/noderb_extension/libuv/deps/pthread-win32/NEWS +1245 -0
  26. data/ext/noderb_extension/libuv/deps/pthread-win32/Nmakefile +24 -0
  27. data/ext/noderb_extension/libuv/deps/pthread-win32/Nmakefile.tests +260 -0
  28. data/ext/noderb_extension/libuv/deps/pthread-win32/PROGRESS +4 -0
  29. data/ext/noderb_extension/libuv/deps/pthread-win32/README +601 -0
  30. data/ext/noderb_extension/libuv/deps/pthread-win32/README.Borland +57 -0
  31. data/ext/noderb_extension/libuv/deps/pthread-win32/README.CV +3036 -0
  32. data/ext/noderb_extension/libuv/deps/pthread-win32/README.NONPORTABLE +783 -0
  33. data/ext/noderb_extension/libuv/deps/pthread-win32/README.Watcom +62 -0
  34. data/ext/noderb_extension/libuv/deps/pthread-win32/README.WinCE +6 -0
  35. data/ext/noderb_extension/libuv/deps/pthread-win32/TODO +7 -0
  36. data/ext/noderb_extension/libuv/deps/pthread-win32/WinCE-PORT +222 -0
  37. data/ext/noderb_extension/libuv/deps/pthread-win32/attr.c +53 -0
  38. data/ext/noderb_extension/libuv/deps/pthread-win32/autostatic.c +69 -0
  39. data/ext/noderb_extension/libuv/deps/pthread-win32/barrier.c +47 -0
  40. data/ext/noderb_extension/libuv/deps/pthread-win32/build/all.gyp +207 -0
  41. data/ext/noderb_extension/libuv/deps/pthread-win32/builddmc.bat +9 -0
  42. data/ext/noderb_extension/libuv/deps/pthread-win32/cancel.c +44 -0
  43. data/ext/noderb_extension/libuv/deps/pthread-win32/cleanup.c +148 -0
  44. data/ext/noderb_extension/libuv/deps/pthread-win32/condvar.c +50 -0
  45. data/ext/noderb_extension/libuv/deps/pthread-win32/config.h +153 -0
  46. data/ext/noderb_extension/libuv/deps/pthread-win32/context.h +74 -0
  47. data/ext/noderb_extension/libuv/deps/pthread-win32/create.c +308 -0
  48. data/ext/noderb_extension/libuv/deps/pthread-win32/dll.c +92 -0
  49. data/ext/noderb_extension/libuv/deps/pthread-win32/errno.c +94 -0
  50. data/ext/noderb_extension/libuv/deps/pthread-win32/exit.c +44 -0
  51. data/ext/noderb_extension/libuv/deps/pthread-win32/fork.c +39 -0
  52. data/ext/noderb_extension/libuv/deps/pthread-win32/global.c +107 -0
  53. data/ext/noderb_extension/libuv/deps/pthread-win32/implement.h +944 -0
  54. data/ext/noderb_extension/libuv/deps/pthread-win32/misc.c +50 -0
  55. data/ext/noderb_extension/libuv/deps/pthread-win32/mutex.c +62 -0
  56. data/ext/noderb_extension/libuv/deps/pthread-win32/need_errno.h +145 -0
  57. data/ext/noderb_extension/libuv/deps/pthread-win32/nonportable.c +47 -0
  58. data/ext/noderb_extension/libuv/deps/pthread-win32/private.c +54 -0
  59. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread.c +66 -0
  60. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread.dsp +142 -0
  61. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread.dsw +29 -0
  62. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread.h +1368 -0
  63. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_destroy.c +79 -0
  64. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getdetachstate.c +86 -0
  65. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getinheritsched.c +51 -0
  66. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getschedparam.c +52 -0
  67. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getschedpolicy.c +61 -0
  68. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getscope.c +54 -0
  69. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getstackaddr.c +97 -0
  70. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getstacksize.c +100 -0
  71. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_init.c +117 -0
  72. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setdetachstate.c +91 -0
  73. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setinheritsched.c +57 -0
  74. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setschedparam.c +63 -0
  75. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setschedpolicy.c +55 -0
  76. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setscope.c +62 -0
  77. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setstackaddr.c +97 -0
  78. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setstacksize.c +110 -0
  79. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrier_destroy.c +103 -0
  80. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrier_init.c +69 -0
  81. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrier_wait.c +104 -0
  82. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrierattr_destroy.c +83 -0
  83. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrierattr_getpshared.c +95 -0
  84. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrierattr_init.c +85 -0
  85. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrierattr_setpshared.c +119 -0
  86. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cancel.c +189 -0
  87. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cond_destroy.c +253 -0
  88. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cond_init.c +167 -0
  89. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cond_signal.c +231 -0
  90. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cond_wait.c +567 -0
  91. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_condattr_destroy.c +86 -0
  92. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_condattr_getpshared.c +97 -0
  93. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_condattr_init.c +87 -0
  94. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_condattr_setpshared.c +117 -0
  95. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_delay_np.c +172 -0
  96. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_detach.c +136 -0
  97. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_equal.c +76 -0
  98. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_exit.c +106 -0
  99. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getconcurrency.c +45 -0
  100. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getschedparam.c +75 -0
  101. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getspecific.c +87 -0
  102. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getunique_np.c +47 -0
  103. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getw32threadhandle_np.c +65 -0
  104. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_join.c +157 -0
  105. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_key_create.c +108 -0
  106. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_key_delete.c +125 -0
  107. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_kill.c +105 -0
  108. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_consistent.c +187 -0
  109. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_destroy.c +148 -0
  110. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_init.c +130 -0
  111. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_lock.c +269 -0
  112. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_timedlock.c +324 -0
  113. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_trylock.c +154 -0
  114. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_unlock.c +175 -0
  115. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_destroy.c +83 -0
  116. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_getkind_np.c +44 -0
  117. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_getpshared.c +95 -0
  118. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_getrobust.c +113 -0
  119. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_gettype.c +56 -0
  120. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_init.c +86 -0
  121. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_setkind_np.c +44 -0
  122. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_setpshared.c +119 -0
  123. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_setrobust.c +119 -0
  124. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_settype.c +143 -0
  125. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_num_processors_np.c +56 -0
  126. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_once.c +79 -0
  127. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_destroy.c +143 -0
  128. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_init.c +109 -0
  129. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_rdlock.c +102 -0
  130. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_timedrdlock.c +109 -0
  131. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_timedwrlock.c +139 -0
  132. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_tryrdlock.c +102 -0
  133. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_trywrlock.c +122 -0
  134. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_unlock.c +93 -0
  135. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_wrlock.c +133 -0
  136. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlockattr_destroy.c +84 -0
  137. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlockattr_getpshared.c +97 -0
  138. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlockattr_init.c +83 -0
  139. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlockattr_setpshared.c +120 -0
  140. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_self.c +141 -0
  141. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setcancelstate.c +125 -0
  142. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setcanceltype.c +126 -0
  143. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setconcurrency.c +53 -0
  144. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setschedparam.c +123 -0
  145. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setspecific.c +167 -0
  146. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_destroy.c +111 -0
  147. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_init.c +123 -0
  148. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_lock.c +80 -0
  149. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_trylock.c +77 -0
  150. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_unlock.c +71 -0
  151. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_testcancel.c +103 -0
  152. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_timechange_handler_np.c +108 -0
  153. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_win32_attach_detach_np.c +258 -0
  154. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_MCS_lock.c +278 -0
  155. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_callUserDestroyRoutines.c +232 -0
  156. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_calloc.c +56 -0
  157. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_cond_check_need_init.c +78 -0
  158. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_getprocessors.c +91 -0
  159. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_is_attr.c +47 -0
  160. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_mutex_check_need_init.c +92 -0
  161. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_new.c +94 -0
  162. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_processInitialize.c +92 -0
  163. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_processTerminate.c +105 -0
  164. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_relmillisecs.c +132 -0
  165. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_reuse.c +151 -0
  166. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_rwlock_cancelwrwait.c +50 -0
  167. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_rwlock_check_need_init.c +77 -0
  168. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_semwait.c +135 -0
  169. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_spinlock_check_need_init.c +78 -0
  170. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_threadDestroy.c +79 -0
  171. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_threadStart.c +357 -0
  172. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_throw.c +189 -0
  173. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_timespec.c +83 -0
  174. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_tkAssocCreate.c +118 -0
  175. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_tkAssocDestroy.c +114 -0
  176. data/ext/noderb_extension/libuv/deps/pthread-win32/rwlock.c +51 -0
  177. data/ext/noderb_extension/libuv/deps/pthread-win32/sched.c +53 -0
  178. data/ext/noderb_extension/libuv/deps/pthread-win32/sched.h +183 -0
  179. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_get_priority_max.c +134 -0
  180. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_get_priority_min.c +135 -0
  181. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_getscheduler.c +71 -0
  182. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_setscheduler.c +83 -0
  183. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_yield.c +71 -0
  184. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_close.c +58 -0
  185. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_destroy.c +144 -0
  186. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_getvalue.c +110 -0
  187. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_init.c +169 -0
  188. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_open.c +58 -0
  189. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_post.c +128 -0
  190. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_post_multiple.c +142 -0
  191. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_timedwait.c +238 -0
  192. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_trywait.c +117 -0
  193. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_unlink.c +58 -0
  194. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_wait.c +187 -0
  195. data/ext/noderb_extension/libuv/deps/pthread-win32/semaphore.c +69 -0
  196. data/ext/noderb_extension/libuv/deps/pthread-win32/semaphore.h +169 -0
  197. data/ext/noderb_extension/libuv/deps/pthread-win32/signal.c +179 -0
  198. data/ext/noderb_extension/libuv/deps/pthread-win32/spin.c +46 -0
  199. data/ext/noderb_extension/libuv/deps/pthread-win32/sync.c +43 -0
  200. data/ext/noderb_extension/libuv/deps/pthread-win32/tsd.c +44 -0
  201. data/ext/noderb_extension/libuv/deps/pthread-win32/version.rc +388 -0
  202. data/ext/noderb_extension/libuv/deps/pthread-win32/w32_CancelableWait.c +161 -0
  203. data/ext/noderb_extension/libuv/doc/desired-api.md +159 -0
  204. data/ext/noderb_extension/libuv/doc/iocp-links.html +574 -0
  205. data/ext/noderb_extension/libuv/include/ares.h +582 -0
  206. data/ext/noderb_extension/libuv/include/ares_version.h +24 -0
  207. data/ext/noderb_extension/libuv/include/eio.h +376 -0
  208. data/ext/noderb_extension/libuv/include/ev.h +835 -0
  209. data/ext/noderb_extension/libuv/include/ngx-queue.h +102 -0
  210. data/ext/noderb_extension/libuv/include/tree.h +762 -0
  211. data/ext/noderb_extension/libuv/include/uv-unix.h +138 -0
  212. data/ext/noderb_extension/libuv/include/uv-win.h +187 -0
  213. data/ext/noderb_extension/libuv/include/uv.h +635 -0
  214. data/ext/noderb_extension/libuv/src/ares/AUTHORS +37 -0
  215. data/ext/noderb_extension/libuv/src/ares/CHANGES +1198 -0
  216. data/ext/noderb_extension/libuv/src/ares/CMakeLists.txt +22 -0
  217. data/ext/noderb_extension/libuv/src/ares/NEWS +21 -0
  218. data/ext/noderb_extension/libuv/src/ares/README +60 -0
  219. data/ext/noderb_extension/libuv/src/ares/README.cares +13 -0
  220. data/ext/noderb_extension/libuv/src/ares/README.msvc +118 -0
  221. data/ext/noderb_extension/libuv/src/ares/README.node +21 -0
  222. data/ext/noderb_extension/libuv/src/ares/RELEASE-NOTES +25 -0
  223. data/ext/noderb_extension/libuv/src/ares/TODO +23 -0
  224. data/ext/noderb_extension/libuv/src/ares/ares__close_sockets.c +66 -0
  225. data/ext/noderb_extension/libuv/src/ares/ares__get_hostent.c +263 -0
  226. data/ext/noderb_extension/libuv/src/ares/ares__read_line.c +71 -0
  227. data/ext/noderb_extension/libuv/src/ares/ares__timeval.c +111 -0
  228. data/ext/noderb_extension/libuv/src/ares/ares_cancel.c +63 -0
  229. data/ext/noderb_extension/libuv/src/ares/ares_data.c +190 -0
  230. data/ext/noderb_extension/libuv/src/ares/ares_data.h +65 -0
  231. data/ext/noderb_extension/libuv/src/ares/ares_destroy.c +105 -0
  232. data/ext/noderb_extension/libuv/src/ares/ares_dns.h +90 -0
  233. data/ext/noderb_extension/libuv/src/ares/ares_expand_name.c +193 -0
  234. data/ext/noderb_extension/libuv/src/ares/ares_expand_string.c +75 -0
  235. data/ext/noderb_extension/libuv/src/ares/ares_fds.c +62 -0
  236. data/ext/noderb_extension/libuv/src/ares/ares_free_hostent.c +39 -0
  237. data/ext/noderb_extension/libuv/src/ares/ares_free_string.c +25 -0
  238. data/ext/noderb_extension/libuv/src/ares/ares_gethostbyaddr.c +292 -0
  239. data/ext/noderb_extension/libuv/src/ares/ares_gethostbyname.c +515 -0
  240. data/ext/noderb_extension/libuv/src/ares/ares_getnameinfo.c +426 -0
  241. data/ext/noderb_extension/libuv/src/ares/ares_getopt.c +122 -0
  242. data/ext/noderb_extension/libuv/src/ares/ares_getopt.h +53 -0
  243. data/ext/noderb_extension/libuv/src/ares/ares_getsock.c +72 -0
  244. data/ext/noderb_extension/libuv/src/ares/ares_init.c +1665 -0
  245. data/ext/noderb_extension/libuv/src/ares/ares_ipv6.h +78 -0
  246. data/ext/noderb_extension/libuv/src/ares/ares_library_init.c +132 -0
  247. data/ext/noderb_extension/libuv/src/ares/ares_library_init.h +39 -0
  248. data/ext/noderb_extension/libuv/src/ares/ares_llist.c +86 -0
  249. data/ext/noderb_extension/libuv/src/ares/ares_llist.h +42 -0
  250. data/ext/noderb_extension/libuv/src/ares/ares_mkquery.c +195 -0
  251. data/ext/noderb_extension/libuv/src/ares/ares_nowarn.c +59 -0
  252. data/ext/noderb_extension/libuv/src/ares/ares_nowarn.h +24 -0
  253. data/ext/noderb_extension/libuv/src/ares/ares_options.c +253 -0
  254. data/ext/noderb_extension/libuv/src/ares/ares_parse_a_reply.c +260 -0
  255. data/ext/noderb_extension/libuv/src/ares/ares_parse_aaaa_reply.c +256 -0
  256. data/ext/noderb_extension/libuv/src/ares/ares_parse_mx_reply.c +170 -0
  257. data/ext/noderb_extension/libuv/src/ares/ares_parse_ns_reply.c +182 -0
  258. data/ext/noderb_extension/libuv/src/ares/ares_parse_ptr_reply.c +208 -0
  259. data/ext/noderb_extension/libuv/src/ares/ares_parse_srv_reply.c +179 -0
  260. data/ext/noderb_extension/libuv/src/ares/ares_parse_txt_reply.c +201 -0
  261. data/ext/noderb_extension/libuv/src/ares/ares_private.h +351 -0
  262. data/ext/noderb_extension/libuv/src/ares/ares_process.c +1296 -0
  263. data/ext/noderb_extension/libuv/src/ares/ares_query.c +183 -0
  264. data/ext/noderb_extension/libuv/src/ares/ares_rules.h +144 -0
  265. data/ext/noderb_extension/libuv/src/ares/ares_search.c +322 -0
  266. data/ext/noderb_extension/libuv/src/ares/ares_send.c +134 -0
  267. data/ext/noderb_extension/libuv/src/ares/ares_setup.h +191 -0
  268. data/ext/noderb_extension/libuv/src/ares/ares_strcasecmp.c +66 -0
  269. data/ext/noderb_extension/libuv/src/ares/ares_strcasecmp.h +30 -0
  270. data/ext/noderb_extension/libuv/src/ares/ares_strdup.c +42 -0
  271. data/ext/noderb_extension/libuv/src/ares/ares_strdup.h +26 -0
  272. data/ext/noderb_extension/libuv/src/ares/ares_strerror.c +56 -0
  273. data/ext/noderb_extension/libuv/src/ares/ares_timeout.c +80 -0
  274. data/ext/noderb_extension/libuv/src/ares/ares_version.c +11 -0
  275. data/ext/noderb_extension/libuv/src/ares/ares_writev.c +79 -0
  276. data/ext/noderb_extension/libuv/src/ares/ares_writev.h +36 -0
  277. data/ext/noderb_extension/libuv/src/ares/bitncmp.c +59 -0
  278. data/ext/noderb_extension/libuv/src/ares/bitncmp.h +26 -0
  279. data/ext/noderb_extension/libuv/src/ares/config_cygwin/ares_config.h +510 -0
  280. data/ext/noderb_extension/libuv/src/ares/config_darwin/ares_config.h +510 -0
  281. data/ext/noderb_extension/libuv/src/ares/config_freebsd/ares_config.h +510 -0
  282. data/ext/noderb_extension/libuv/src/ares/config_linux/ares_config.h +510 -0
  283. data/ext/noderb_extension/libuv/src/ares/config_openbsd/ares_config.h +510 -0
  284. data/ext/noderb_extension/libuv/src/ares/config_sunos/ares_config.h +510 -0
  285. data/ext/noderb_extension/libuv/src/ares/config_win32/ares_config.h +369 -0
  286. data/ext/noderb_extension/libuv/src/ares/get_ver.awk +35 -0
  287. data/ext/noderb_extension/libuv/src/ares/inet_net_pton.c +450 -0
  288. data/ext/noderb_extension/libuv/src/ares/inet_net_pton.h +31 -0
  289. data/ext/noderb_extension/libuv/src/ares/inet_ntop.c +232 -0
  290. data/ext/noderb_extension/libuv/src/ares/inet_ntop.h +27 -0
  291. data/ext/noderb_extension/libuv/src/ares/nameser.h +193 -0
  292. data/ext/noderb_extension/libuv/src/ares/setup_once.h +488 -0
  293. data/ext/noderb_extension/libuv/src/ares/windows_port.c +22 -0
  294. data/ext/noderb_extension/libuv/src/eio/Changes +63 -0
  295. data/ext/noderb_extension/libuv/src/eio/LICENSE +36 -0
  296. data/ext/noderb_extension/libuv/src/eio/Makefile.am +15 -0
  297. data/ext/noderb_extension/libuv/src/eio/aclocal.m4 +8957 -0
  298. data/ext/noderb_extension/libuv/src/eio/autogen.sh +3 -0
  299. data/ext/noderb_extension/libuv/src/eio/config.h.in +86 -0
  300. data/ext/noderb_extension/libuv/src/eio/config_cygwin.h +77 -0
  301. data/ext/noderb_extension/libuv/src/eio/config_darwin.h +137 -0
  302. data/ext/noderb_extension/libuv/src/eio/config_freebsd.h +78 -0
  303. data/ext/noderb_extension/libuv/src/eio/config_linux.h +101 -0
  304. data/ext/noderb_extension/libuv/src/eio/config_sunos.h +81 -0
  305. data/ext/noderb_extension/libuv/src/eio/configure.ac +22 -0
  306. data/ext/noderb_extension/libuv/src/eio/demo.c +194 -0
  307. data/ext/noderb_extension/libuv/src/eio/ecb.h +370 -0
  308. data/ext/noderb_extension/libuv/src/eio/eio.3 +3428 -0
  309. data/ext/noderb_extension/libuv/src/eio/eio.c +2562 -0
  310. data/ext/noderb_extension/libuv/src/eio/eio.pod +969 -0
  311. data/ext/noderb_extension/libuv/src/eio/libeio.m4 +195 -0
  312. data/ext/noderb_extension/libuv/src/eio/xthread.h +164 -0
  313. data/ext/noderb_extension/libuv/src/ev/Changes +388 -0
  314. data/ext/noderb_extension/libuv/src/ev/LICENSE +36 -0
  315. data/ext/noderb_extension/libuv/src/ev/Makefile.am +18 -0
  316. data/ext/noderb_extension/libuv/src/ev/Makefile.in +771 -0
  317. data/ext/noderb_extension/libuv/src/ev/README +58 -0
  318. data/ext/noderb_extension/libuv/src/ev/aclocal.m4 +8957 -0
  319. data/ext/noderb_extension/libuv/src/ev/autogen.sh +6 -0
  320. data/ext/noderb_extension/libuv/src/ev/config.guess +1526 -0
  321. data/ext/noderb_extension/libuv/src/ev/config.h.in +125 -0
  322. data/ext/noderb_extension/libuv/src/ev/config.sub +1658 -0
  323. data/ext/noderb_extension/libuv/src/ev/config_cygwin.h +123 -0
  324. data/ext/noderb_extension/libuv/src/ev/config_darwin.h +122 -0
  325. data/ext/noderb_extension/libuv/src/ev/config_freebsd.h +120 -0
  326. data/ext/noderb_extension/libuv/src/ev/config_linux.h +130 -0
  327. data/ext/noderb_extension/libuv/src/ev/config_sunos.h +122 -0
  328. data/ext/noderb_extension/libuv/src/ev/configure +13037 -0
  329. data/ext/noderb_extension/libuv/src/ev/configure.ac +18 -0
  330. data/ext/noderb_extension/libuv/src/ev/depcomp +630 -0
  331. data/ext/noderb_extension/libuv/src/ev/ev++.h +816 -0
  332. data/ext/noderb_extension/libuv/src/ev/ev.3 +5311 -0
  333. data/ext/noderb_extension/libuv/src/ev/ev.c +3913 -0
  334. data/ext/noderb_extension/libuv/src/ev/ev.pod +5243 -0
  335. data/ext/noderb_extension/libuv/src/ev/ev_epoll.c +266 -0
  336. data/ext/noderb_extension/libuv/src/ev/ev_kqueue.c +198 -0
  337. data/ext/noderb_extension/libuv/src/ev/ev_poll.c +148 -0
  338. data/ext/noderb_extension/libuv/src/ev/ev_port.c +179 -0
  339. data/ext/noderb_extension/libuv/src/ev/ev_select.c +310 -0
  340. data/ext/noderb_extension/libuv/src/ev/ev_vars.h +203 -0
  341. data/ext/noderb_extension/libuv/src/ev/ev_win32.c +153 -0
  342. data/ext/noderb_extension/libuv/src/ev/ev_wrap.h +196 -0
  343. data/ext/noderb_extension/libuv/src/ev/event.c +402 -0
  344. data/ext/noderb_extension/libuv/src/ev/event.h +170 -0
  345. data/ext/noderb_extension/libuv/src/ev/install-sh +294 -0
  346. data/ext/noderb_extension/libuv/src/ev/libev.m4 +39 -0
  347. data/ext/noderb_extension/libuv/src/ev/ltmain.sh +8413 -0
  348. data/ext/noderb_extension/libuv/src/ev/missing +336 -0
  349. data/ext/noderb_extension/libuv/src/ev/mkinstalldirs +111 -0
  350. data/ext/noderb_extension/libuv/src/uv-common.c +172 -0
  351. data/ext/noderb_extension/libuv/src/uv-common.h +53 -0
  352. data/ext/noderb_extension/libuv/src/uv-cygwin.c +52 -0
  353. data/ext/noderb_extension/libuv/src/uv-darwin.c +64 -0
  354. data/ext/noderb_extension/libuv/src/uv-eio.c +113 -0
  355. data/ext/noderb_extension/libuv/src/uv-eio.h +13 -0
  356. data/ext/noderb_extension/libuv/src/uv-freebsd.c +65 -0
  357. data/ext/noderb_extension/libuv/src/uv-linux.c +51 -0
  358. data/ext/noderb_extension/libuv/src/uv-sunos.c +60 -0
  359. data/ext/noderb_extension/libuv/src/uv-unix.c +2408 -0
  360. data/ext/noderb_extension/libuv/src/win/async.c +129 -0
  361. data/ext/noderb_extension/libuv/src/win/cares.c +304 -0
  362. data/ext/noderb_extension/libuv/src/win/core.c +155 -0
  363. data/ext/noderb_extension/libuv/src/win/error.c +140 -0
  364. data/ext/noderb_extension/libuv/src/win/getaddrinfo.c +341 -0
  365. data/ext/noderb_extension/libuv/src/win/handle.c +176 -0
  366. data/ext/noderb_extension/libuv/src/win/internal.h +237 -0
  367. data/ext/noderb_extension/libuv/src/win/loop-watcher.c +128 -0
  368. data/ext/noderb_extension/libuv/src/win/pipe.c +828 -0
  369. data/ext/noderb_extension/libuv/src/win/process.c +936 -0
  370. data/ext/noderb_extension/libuv/src/win/req.c +141 -0
  371. data/ext/noderb_extension/libuv/src/win/stdio.c +75 -0
  372. data/ext/noderb_extension/libuv/src/win/stream.c +149 -0
  373. data/ext/noderb_extension/libuv/src/win/tcp.c +895 -0
  374. data/ext/noderb_extension/libuv/src/win/timer.c +269 -0
  375. data/ext/noderb_extension/libuv/src/win/util.c +82 -0
  376. data/ext/noderb_extension/libuv/test/benchmark-ares.c +117 -0
  377. data/ext/noderb_extension/libuv/test/benchmark-getaddrinfo.c +90 -0
  378. data/ext/noderb_extension/libuv/test/benchmark-list.h +77 -0
  379. data/ext/noderb_extension/libuv/test/benchmark-ping-pongs.c +210 -0
  380. data/ext/noderb_extension/libuv/test/benchmark-pound.c +237 -0
  381. data/ext/noderb_extension/libuv/test/benchmark-pump.c +459 -0
  382. data/ext/noderb_extension/libuv/test/benchmark-sizes.c +39 -0
  383. data/ext/noderb_extension/libuv/test/benchmark-spawn.c +154 -0
  384. data/ext/noderb_extension/libuv/test/dns-server.c +323 -0
  385. data/ext/noderb_extension/libuv/test/echo-server.c +299 -0
  386. data/ext/noderb_extension/libuv/test/run-benchmarks.c +64 -0
  387. data/ext/noderb_extension/libuv/test/run-tests.c +82 -0
  388. data/ext/noderb_extension/libuv/test/runner-unix.c +335 -0
  389. data/ext/noderb_extension/libuv/test/runner-unix.h +36 -0
  390. data/ext/noderb_extension/libuv/test/runner-win.c +343 -0
  391. data/ext/noderb_extension/libuv/test/runner-win.h +42 -0
  392. data/ext/noderb_extension/libuv/test/runner.c +311 -0
  393. data/ext/noderb_extension/libuv/test/runner.h +155 -0
  394. data/ext/noderb_extension/libuv/test/task.h +111 -0
  395. data/ext/noderb_extension/libuv/test/test-async.c +218 -0
  396. data/ext/noderb_extension/libuv/test/test-callback-stack.c +205 -0
  397. data/ext/noderb_extension/libuv/test/test-connection-fail.c +149 -0
  398. data/ext/noderb_extension/libuv/test/test-delayed-accept.c +198 -0
  399. data/ext/noderb_extension/libuv/test/test-fail-always.c +29 -0
  400. data/ext/noderb_extension/libuv/test/test-get-currentexe.c +53 -0
  401. data/ext/noderb_extension/libuv/test/test-getaddrinfo.c +110 -0
  402. data/ext/noderb_extension/libuv/test/test-gethostbyname.c +192 -0
  403. data/ext/noderb_extension/libuv/test/test-getsockname.c +196 -0
  404. data/ext/noderb_extension/libuv/test/test-hrtime.c +51 -0
  405. data/ext/noderb_extension/libuv/test/test-idle.c +83 -0
  406. data/ext/noderb_extension/libuv/test/test-list.h +165 -0
  407. data/ext/noderb_extension/libuv/test/test-loop-handles.c +361 -0
  408. data/ext/noderb_extension/libuv/test/test-pass-always.c +28 -0
  409. data/ext/noderb_extension/libuv/test/test-ping-pong.c +256 -0
  410. data/ext/noderb_extension/libuv/test/test-pipe-bind-error.c +148 -0
  411. data/ext/noderb_extension/libuv/test/test-ref.c +91 -0
  412. data/ext/noderb_extension/libuv/test/test-shutdown-eof.c +183 -0
  413. data/ext/noderb_extension/libuv/test/test-spawn.c +345 -0
  414. data/ext/noderb_extension/libuv/test/test-tcp-bind-error.c +204 -0
  415. data/ext/noderb_extension/libuv/test/test-tcp-bind6-error.c +164 -0
  416. data/ext/noderb_extension/libuv/test/test-tcp-writealot.c +198 -0
  417. data/ext/noderb_extension/libuv/test/test-timer-again.c +141 -0
  418. data/ext/noderb_extension/libuv/test/test-timer.c +134 -0
  419. data/ext/noderb_extension/noderb.c +340 -0
  420. data/ext/noderb_extension/noderb.h +2 -0
  421. data/lib/noderb/connection.rb +21 -0
  422. data/lib/noderb/process.rb +17 -0
  423. data/lib/noderb.rb +25 -0
  424. metadata +470 -0
@@ -0,0 +1,2562 @@
1
+ /*
2
+ * libeio implementation
3
+ *
4
+ * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libeio@schmorp.de>
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without modifica-
8
+ * tion, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * Alternatively, the contents of this file may be used under the terms of
29
+ * the GNU General Public License ("GPL") version 2 or any later version,
30
+ * in which case the provisions of the GPL are applicable instead of
31
+ * the above. If you wish to allow the use of your version of this file
32
+ * only under the terms of the GPL and not to allow others to use your
33
+ * version of this file under the BSD license, indicate your decision
34
+ * by deleting the provisions above and replace them with the notice
35
+ * and other provisions required by the GPL. If you do not delete the
36
+ * provisions above, a recipient may use your version of this file under
37
+ * either the BSD or the GPL.
38
+ */
39
+
40
+ #ifdef EIO_CONFIG_H
41
+ # include EIO_CONFIG_H
42
+ #endif
43
+
44
+ /* Undone by libuv for easy build scripts.
45
+ * #ifndef _WIN32
46
+ * # include "config.h"
47
+ * #endif
48
+ */
49
+
50
+ #include "eio.h"
51
+ #include "ecb.h"
52
+
53
+ #ifdef EIO_STACKSIZE
54
+ # define X_STACKSIZE EIO_STACKSIZE
55
+ #endif
56
+ #include "xthread.h"
57
+
58
+ #include <errno.h>
59
+ #include <stddef.h>
60
+ #include <stdlib.h>
61
+ #include <string.h>
62
+ #include <errno.h>
63
+ #include <sys/types.h>
64
+ #include <sys/stat.h>
65
+ #include <limits.h>
66
+ #include <fcntl.h>
67
+ #include <assert.h>
68
+
69
+ /* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */
70
+ /* intptr_t only comes from stdint.h, says idiot openbsd coder */
71
+ #if HAVE_STDINT_H
72
+ # include <stdint.h>
73
+ #endif
74
+
75
+ #ifndef ECANCELED
76
+ # define ECANCELED EDOM
77
+ #endif
78
+ #ifndef ELOOP
79
+ # define ELOOP EDOM
80
+ #endif
81
+
82
+ #if !defined(ENOTSOCK) && defined(WSAENOTSOCK)
83
+ # define ENOTSOCK WSAENOTSOCK
84
+ #endif
85
+
86
+ static void eio_destroy (eio_req *req);
87
+
88
+ #ifndef EIO_FINISH
89
+ # define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0
90
+ #endif
91
+
92
+ #ifndef EIO_DESTROY
93
+ # define EIO_DESTROY(req) do { if ((req)->destroy) (req)->destroy (req); } while (0)
94
+ #endif
95
+
96
+ #ifndef EIO_FEED
97
+ # define EIO_FEED(req) do { if ((req)->feed ) (req)->feed (req); } while (0)
98
+ #endif
99
+
100
+ #ifndef EIO_FD_TO_WIN32_HANDLE
101
+ # define EIO_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)
102
+ #endif
103
+ #ifndef EIO_WIN32_HANDLE_TO_FD
104
+ # define EIO_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)
105
+ #endif
106
+
107
+ #define EIO_ERRNO(errval,retval) ((errno = errval), retval)
108
+
109
+ #define EIO_ENOSYS() EIO_ERRNO (ENOSYS, -1)
110
+
111
+ #ifdef _WIN32
112
+
113
+ #undef PAGESIZE
114
+ #define PAGESIZE 4096 /* GetSystemInfo? */
115
+
116
+ /* TODO: look at how perl does stat (non-sloppy), unlink (ro-files), utime, link */
117
+
118
+ #ifdef EIO_STRUCT_STATI64
119
+ /* look at perl's non-sloppy stat */
120
+ #define stat(path,buf) _stati64 (path,buf)
121
+ #define fstat(fd,buf) _fstati64 (fd,buf)
122
+ #endif
123
+ #define lstat(path,buf) stat (path,buf)
124
+ #define fsync(fd) (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1))
125
+ #define mkdir(path,mode) _mkdir (path)
126
+ #define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1))
127
+
128
+ #define chmod(path,mode) _chmod (path, mode)
129
+ #define dup(fd) _dup (fd)
130
+ #define dup2(fd1,fd2) _dup2 (fd1, fd2)
131
+
132
+ #define fchmod(fd,mode) EIO_ENOSYS ()
133
+ #define chown(path,uid,gid) EIO_ENOSYS ()
134
+ #define fchown(fd,uid,gid) EIO_ENOSYS ()
135
+ #define truncate(path,offs) EIO_ENOSYS () /* far-miss: SetEndOfFile */
136
+ #define ftruncate(fd,offs) EIO_ENOSYS () /* near-miss: SetEndOfFile */
137
+ #define mknod(path,mode,dev) EIO_ENOSYS ()
138
+ #define sync() EIO_ENOSYS ()
139
+ #define readlink(path,buf,s) EIO_ENOSYS ()
140
+ #define statvfs(path,buf) EIO_ENOSYS ()
141
+ #define fstatvfs(fd,buf) EIO_ENOSYS ()
142
+
143
+ /* rename() uses MoveFile, which fails to overwrite */
144
+ #define rename(old,neu) eio__rename (old, neu)
145
+
146
+ static int
147
+ eio__rename (const char *old, const char *neu)
148
+ {
149
+ if (MoveFileEx (old, neu, MOVEFILE_REPLACE_EXISTING))
150
+ return 0;
151
+
152
+ /* should steal _dosmaperr */
153
+ switch (GetLastError ())
154
+ {
155
+ case ERROR_FILE_NOT_FOUND:
156
+ case ERROR_PATH_NOT_FOUND:
157
+ case ERROR_INVALID_DRIVE:
158
+ case ERROR_NO_MORE_FILES:
159
+ case ERROR_BAD_NETPATH:
160
+ case ERROR_BAD_NET_NAME:
161
+ case ERROR_BAD_PATHNAME:
162
+ case ERROR_FILENAME_EXCED_RANGE:
163
+ errno = ENOENT;
164
+ break;
165
+
166
+ default:
167
+ errno = EACCES;
168
+ break;
169
+ }
170
+
171
+ return -1;
172
+ }
173
+
174
+ /* we could even stat and see if it exists */
175
+ static int
176
+ symlink (const char *old, const char *neu)
177
+ {
178
+ #if WINVER >= 0x0600
179
+ if (CreateSymbolicLink (neu, old, 1))
180
+ return 0;
181
+
182
+ if (CreateSymbolicLink (neu, old, 0))
183
+ return 0;
184
+ #endif
185
+
186
+ return EIO_ERRNO (ENOENT, -1);
187
+ }
188
+
189
+ /* POSIX API only */
190
+ #define CreateHardLink(neu,old,flags) 0
191
+ #define CreateSymbolicLink(neu,old,flags) 0
192
+
193
+ struct statvfs
194
+ {
195
+ int dummy;
196
+ };
197
+
198
+ #define DT_DIR EIO_DT_DIR
199
+ #define DT_REG EIO_DT_REG
200
+ #define D_NAME(entp) entp.cFileName
201
+ #define D_TYPE(entp) (entp.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? DT_DIR : DT_REG)
202
+
203
+ #include <sys/utime.h>
204
+ #define utime(path, times) _utime(path, times)
205
+ #define utimbuf _utimbuf
206
+
207
+ #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
208
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
209
+ #else
210
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
211
+ #endif
212
+
213
+ struct timezone
214
+ {
215
+ int tz_minuteswest; /* minutes W of Greenwich */
216
+ int tz_dsttime; /* type of dst correction */
217
+ };
218
+
219
+ static int gettimeofday(struct timeval *tv, struct timezone *tz)
220
+ {
221
+ FILETIME ft;
222
+ unsigned __int64 tmpres = 0;
223
+ static int tzflag;
224
+
225
+ if (NULL != tv)
226
+ {
227
+ GetSystemTimeAsFileTime(&ft);
228
+
229
+ tmpres |= ft.dwHighDateTime;
230
+ tmpres <<= 32;
231
+ tmpres |= ft.dwLowDateTime;
232
+
233
+ /*converting file time to unix epoch*/
234
+ tmpres -= DELTA_EPOCH_IN_MICROSECS;
235
+ tmpres /= 10; /*convert into microseconds*/
236
+ tv->tv_sec = (long)(tmpres / 1000000UL);
237
+ tv->tv_usec = (long)(tmpres % 1000000UL);
238
+ }
239
+
240
+ if (NULL != tz)
241
+ {
242
+ if (!tzflag)
243
+ {
244
+ _tzset();
245
+ tzflag++;
246
+ }
247
+ tz->tz_minuteswest = _timezone / 60;
248
+ tz->tz_dsttime = _daylight;
249
+ }
250
+
251
+ return 0;
252
+ }
253
+
254
+ #else
255
+
256
+ #include <sys/time.h>
257
+ #include <sys/select.h>
258
+ #include <sys/statvfs.h>
259
+ #include <unistd.h>
260
+ #include <signal.h>
261
+ #include <dirent.h>
262
+
263
+ #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES
264
+ #include <sys/mman.h>
265
+ #endif
266
+
267
+ #define D_NAME(entp) entp->d_name
268
+
269
+ /* POSIX_SOURCE is useless on bsd's, and XOPEN_SOURCE is unreliable there, too */
270
+ #if __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
271
+ #define _DIRENT_HAVE_D_TYPE /* sigh */
272
+ #define D_INO(de) (de)->d_fileno
273
+ #define D_NAMLEN(de) (de)->d_namlen
274
+ #elif __linux || defined d_ino || _XOPEN_SOURCE >= 600
275
+ #define D_INO(de) (de)->d_ino
276
+ #endif
277
+
278
+ #ifdef _D_EXACT_NAMLEN
279
+ #undef D_NAMLEN
280
+ #define D_NAMLEN(de) _D_EXACT_NAMLEN (de)
281
+ #endif
282
+
283
+ #ifdef _DIRENT_HAVE_D_TYPE
284
+ #define D_TYPE(de) (de)->d_type
285
+ #endif
286
+
287
+ #ifndef EIO_STRUCT_DIRENT
288
+ #define EIO_STRUCT_DIRENT struct dirent
289
+ #endif
290
+
291
+ #endif
292
+
293
+ #if HAVE_UTIMES
294
+ # include <utime.h>
295
+ #endif
296
+
297
+ #if HAVE_SYS_SYSCALL_H
298
+ # include <sys/syscall.h>
299
+ #endif
300
+
301
+ #if HAVE_SYS_PRCTL_H
302
+ # include <sys/prctl.h>
303
+ #endif
304
+
305
+ #if HAVE_SENDFILE
306
+ # if __linux
307
+ # include <sys/sendfile.h>
308
+ # elif __FreeBSD__ || defined __APPLE__
309
+ # include <sys/socket.h>
310
+ # include <sys/uio.h>
311
+ # elif __hpux
312
+ # include <sys/socket.h>
313
+ # elif __solaris
314
+ # include <sys/sendfile.h>
315
+ # else
316
+ # error sendfile support requested but not available
317
+ # endif
318
+ #endif
319
+
320
+ #ifndef D_TYPE
321
+ # define D_TYPE(de) 0
322
+ #endif
323
+ #ifndef D_INO
324
+ # define D_INO(de) 0
325
+ #endif
326
+ #ifndef D_NAMLEN
327
+ # define D_NAMLEN(entp) strlen (D_NAME (entp))
328
+ #endif
329
+
330
+ /* used for struct dirent, AIX doesn't provide it */
331
+ #ifndef NAME_MAX
332
+ # define NAME_MAX 4096
333
+ #endif
334
+
335
+ /* used for readlink etc. */
336
+ #ifndef PATH_MAX
337
+ # define PATH_MAX 4096
338
+ #endif
339
+
340
+ /* buffer size for various temporary buffers */
341
+ #define EIO_BUFSIZE 65536
342
+
343
+ #define dBUF \
344
+ char *eio_buf = malloc (EIO_BUFSIZE); \
345
+ errno = ENOMEM; \
346
+ if (!eio_buf) \
347
+ return -1
348
+
349
+ #define FUBd \
350
+ free (eio_buf)
351
+
352
+ #define EIO_TICKS ((1000000 + 1023) >> 10)
353
+
354
+ #define ETP_PRI_MIN EIO_PRI_MIN
355
+ #define ETP_PRI_MAX EIO_PRI_MAX
356
+
357
+ struct etp_worker;
358
+
359
+ #define ETP_REQ eio_req
360
+ #define ETP_DESTROY(req) eio_destroy (req)
361
+ static int eio_finish (eio_req *req);
362
+ #define ETP_FINISH(req) eio_finish (req)
363
+ static void eio_execute (struct etp_worker *self, eio_req *req);
364
+ #define ETP_EXECUTE(wrk,req) eio_execute (wrk,req)
365
+
366
+ /*****************************************************************************/
367
+
368
+ #define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1)
369
+
370
+ /* calculate time difference in ~1/EIO_TICKS of a second */
371
+ ecb_inline int
372
+ tvdiff (struct timeval *tv1, struct timeval *tv2)
373
+ {
374
+ return (tv2->tv_sec - tv1->tv_sec ) * EIO_TICKS
375
+ + ((tv2->tv_usec - tv1->tv_usec) >> 10);
376
+ }
377
+
378
+ static unsigned int started, idle, wanted = 4;
379
+
380
+ static void (*want_poll_cb) (void);
381
+ static void (*done_poll_cb) (void);
382
+
383
+ static unsigned int max_poll_time; /* reslock */
384
+ static unsigned int max_poll_reqs; /* reslock */
385
+
386
+ static unsigned int nreqs; /* reqlock */
387
+ static unsigned int nready; /* reqlock */
388
+ static unsigned int npending; /* reqlock */
389
+ static unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */
390
+ static unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */
391
+
392
+ static xmutex_t wrklock;
393
+ static xmutex_t reslock;
394
+ static xmutex_t reqlock;
395
+ static xcond_t reqwait;
396
+
397
+ #if !HAVE_PREADWRITE
398
+ /*
399
+ * make our pread/pwrite emulation safe against themselves, but not against
400
+ * normal read/write by using a mutex. slows down execution a lot,
401
+ * but that's your problem, not mine.
402
+ */
403
+ static xmutex_t preadwritelock;
404
+ #endif
405
+
406
+ typedef struct etp_worker
407
+ {
408
+ /* locked by wrklock */
409
+ struct etp_worker *prev, *next;
410
+
411
+ xthread_t tid;
412
+
413
+ /* locked by reslock, reqlock or wrklock */
414
+ ETP_REQ *req; /* currently processed request */
415
+
416
+ #ifdef ETP_WORKER_COMMON
417
+ ETP_WORKER_COMMON
418
+ #endif
419
+ } etp_worker;
420
+
421
+ static etp_worker wrk_first; /* NOT etp */
422
+
423
+ #define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock)
424
+ #define ETP_WORKER_UNLOCK(wrk) X_UNLOCK (wrklock)
425
+
426
+ /* worker threads management */
427
+
428
+ static void ecb_cold
429
+ etp_worker_clear (etp_worker *wrk)
430
+ {
431
+ }
432
+
433
+ static void ecb_cold
434
+ etp_worker_free (etp_worker *wrk)
435
+ {
436
+ wrk->next->prev = wrk->prev;
437
+ wrk->prev->next = wrk->next;
438
+
439
+ free (wrk);
440
+ }
441
+
442
+ static unsigned int
443
+ etp_nreqs (void)
444
+ {
445
+ int retval;
446
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
447
+ retval = nreqs;
448
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
449
+ return retval;
450
+ }
451
+
452
+ static unsigned int
453
+ etp_nready (void)
454
+ {
455
+ unsigned int retval;
456
+
457
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
458
+ retval = nready;
459
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
460
+
461
+ return retval;
462
+ }
463
+
464
+ static unsigned int
465
+ etp_npending (void)
466
+ {
467
+ unsigned int retval;
468
+
469
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
470
+ retval = npending;
471
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
472
+
473
+ return retval;
474
+ }
475
+
476
+ static unsigned int
477
+ etp_nthreads (void)
478
+ {
479
+ unsigned int retval;
480
+
481
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
482
+ retval = started;
483
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
484
+
485
+ return retval;
486
+ }
487
+
488
+ /*
489
+ * a somewhat faster data structure might be nice, but
490
+ * with 8 priorities this actually needs <20 insns
491
+ * per shift, the most expensive operation.
492
+ */
493
+ typedef struct {
494
+ ETP_REQ *qs[ETP_NUM_PRI], *qe[ETP_NUM_PRI]; /* qstart, qend */
495
+ int size;
496
+ } etp_reqq;
497
+
498
+ static etp_reqq req_queue;
499
+ static etp_reqq res_queue;
500
+
501
+ static void ecb_noinline ecb_cold
502
+ reqq_init (etp_reqq *q)
503
+ {
504
+ int pri;
505
+
506
+ for (pri = 0; pri < ETP_NUM_PRI; ++pri)
507
+ q->qs[pri] = q->qe[pri] = 0;
508
+
509
+ q->size = 0;
510
+ }
511
+
512
+ static int ecb_noinline
513
+ reqq_push (etp_reqq *q, ETP_REQ *req)
514
+ {
515
+ int pri = req->pri;
516
+ req->next = 0;
517
+
518
+ if (q->qe[pri])
519
+ {
520
+ q->qe[pri]->next = req;
521
+ q->qe[pri] = req;
522
+ }
523
+ else
524
+ q->qe[pri] = q->qs[pri] = req;
525
+
526
+ return q->size++;
527
+ }
528
+
529
+ static ETP_REQ * ecb_noinline
530
+ reqq_shift (etp_reqq *q)
531
+ {
532
+ int pri;
533
+
534
+ if (!q->size)
535
+ return 0;
536
+
537
+ --q->size;
538
+
539
+ for (pri = ETP_NUM_PRI; pri--; )
540
+ {
541
+ eio_req *req = q->qs[pri];
542
+
543
+ if (req)
544
+ {
545
+ if (!(q->qs[pri] = (eio_req *)req->next))
546
+ q->qe[pri] = 0;
547
+
548
+ return req;
549
+ }
550
+ }
551
+
552
+ abort ();
553
+ }
554
+
555
+ static int ecb_cold
556
+ etp_init (void (*want_poll)(void), void (*done_poll)(void))
557
+ {
558
+ X_MUTEX_CREATE (wrklock);
559
+ X_MUTEX_CREATE (reslock);
560
+ X_MUTEX_CREATE (reqlock);
561
+ X_COND_CREATE (reqwait);
562
+
563
+ reqq_init (&req_queue);
564
+ reqq_init (&res_queue);
565
+
566
+ wrk_first.next =
567
+ wrk_first.prev = &wrk_first;
568
+
569
+ started = 0;
570
+ idle = 0;
571
+ nreqs = 0;
572
+ nready = 0;
573
+ npending = 0;
574
+
575
+ want_poll_cb = want_poll;
576
+ done_poll_cb = done_poll;
577
+
578
+ return 0;
579
+ }
580
+
581
+ X_THREAD_PROC (etp_proc);
582
+
583
+ static void ecb_cold
584
+ etp_start_thread (void)
585
+ {
586
+ etp_worker *wrk = calloc (1, sizeof (etp_worker));
587
+
588
+ /*TODO*/
589
+ assert (("unable to allocate worker thread data", wrk));
590
+
591
+ X_LOCK (wrklock);
592
+
593
+ if (thread_create (&wrk->tid, etp_proc, (void *)wrk))
594
+ {
595
+ wrk->prev = &wrk_first;
596
+ wrk->next = wrk_first.next;
597
+ wrk_first.next->prev = wrk;
598
+ wrk_first.next = wrk;
599
+ ++started;
600
+ }
601
+ else
602
+ free (wrk);
603
+
604
+ X_UNLOCK (wrklock);
605
+ }
606
+
607
+ static void
608
+ etp_maybe_start_thread (void)
609
+ {
610
+ if (ecb_expect_true (etp_nthreads () >= wanted))
611
+ return;
612
+
613
+ /* todo: maybe use idle here, but might be less exact */
614
+ if (ecb_expect_true (0 <= (int)etp_nthreads () + (int)etp_npending () - (int)etp_nreqs ()))
615
+ return;
616
+
617
+ etp_start_thread ();
618
+ }
619
+
620
+ static void ecb_cold
621
+ etp_end_thread (void)
622
+ {
623
+ eio_req *req = calloc (1, sizeof (eio_req));
624
+
625
+ req->type = -1;
626
+ req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
627
+
628
+ X_LOCK (reqlock);
629
+ reqq_push (&req_queue, req);
630
+ X_COND_SIGNAL (reqwait);
631
+ X_UNLOCK (reqlock);
632
+
633
+ X_LOCK (wrklock);
634
+ --started;
635
+ X_UNLOCK (wrklock);
636
+ }
637
+
638
+ static int
639
+ etp_poll (void)
640
+ {
641
+ unsigned int maxreqs;
642
+ unsigned int maxtime;
643
+ struct timeval tv_start, tv_now;
644
+
645
+ X_LOCK (reslock);
646
+ maxreqs = max_poll_reqs;
647
+ maxtime = max_poll_time;
648
+ X_UNLOCK (reslock);
649
+
650
+ if (maxtime)
651
+ gettimeofday (&tv_start, 0);
652
+
653
+ for (;;)
654
+ {
655
+ ETP_REQ *req;
656
+
657
+ etp_maybe_start_thread ();
658
+
659
+ X_LOCK (reslock);
660
+ req = reqq_shift (&res_queue);
661
+
662
+ if (req)
663
+ {
664
+ --npending;
665
+
666
+ if (!res_queue.size && done_poll_cb)
667
+ done_poll_cb ();
668
+ }
669
+
670
+ X_UNLOCK (reslock);
671
+
672
+ if (!req)
673
+ return 0;
674
+
675
+ X_LOCK (reqlock);
676
+ --nreqs;
677
+ X_UNLOCK (reqlock);
678
+
679
+ if (ecb_expect_false (req->type == EIO_GROUP && req->size))
680
+ {
681
+ req->int1 = 1; /* mark request as delayed */
682
+ continue;
683
+ }
684
+ else
685
+ {
686
+ int res = ETP_FINISH (req);
687
+ if (ecb_expect_false (res))
688
+ return res;
689
+ }
690
+
691
+ if (ecb_expect_false (maxreqs && !--maxreqs))
692
+ break;
693
+
694
+ if (maxtime)
695
+ {
696
+ gettimeofday (&tv_now, 0);
697
+
698
+ if (tvdiff (&tv_start, &tv_now) >= maxtime)
699
+ break;
700
+ }
701
+ }
702
+
703
+ errno = EAGAIN;
704
+ return -1;
705
+ }
706
+
707
+ static void
708
+ etp_cancel (ETP_REQ *req)
709
+ {
710
+ req->cancelled = 1;
711
+
712
+ eio_grp_cancel (req);
713
+ }
714
+
715
+ static void
716
+ etp_submit (ETP_REQ *req)
717
+ {
718
+ req->pri -= ETP_PRI_MIN;
719
+
720
+ if (ecb_expect_false (req->pri < ETP_PRI_MIN - ETP_PRI_MIN)) req->pri = ETP_PRI_MIN - ETP_PRI_MIN;
721
+ if (ecb_expect_false (req->pri > ETP_PRI_MAX - ETP_PRI_MIN)) req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
722
+
723
+ if (ecb_expect_false (req->type == EIO_GROUP))
724
+ {
725
+ /* I hope this is worth it :/ */
726
+ X_LOCK (reqlock);
727
+ ++nreqs;
728
+ X_UNLOCK (reqlock);
729
+
730
+ X_LOCK (reslock);
731
+
732
+ ++npending;
733
+
734
+ if (!reqq_push (&res_queue, req) && want_poll_cb)
735
+ want_poll_cb ();
736
+
737
+ X_UNLOCK (reslock);
738
+ }
739
+ else
740
+ {
741
+ X_LOCK (reqlock);
742
+ ++nreqs;
743
+ ++nready;
744
+ reqq_push (&req_queue, req);
745
+ X_COND_SIGNAL (reqwait);
746
+ X_UNLOCK (reqlock);
747
+
748
+ etp_maybe_start_thread ();
749
+ }
750
+ }
751
+
752
+ static void ecb_cold
753
+ etp_set_max_poll_time (double nseconds)
754
+ {
755
+ if (WORDACCESS_UNSAFE) X_LOCK (reslock);
756
+ max_poll_time = nseconds * EIO_TICKS;
757
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reslock);
758
+ }
759
+
760
+ static void ecb_cold
761
+ etp_set_max_poll_reqs (unsigned int maxreqs)
762
+ {
763
+ if (WORDACCESS_UNSAFE) X_LOCK (reslock);
764
+ max_poll_reqs = maxreqs;
765
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reslock);
766
+ }
767
+
768
+ static void ecb_cold
769
+ etp_set_max_idle (unsigned int nthreads)
770
+ {
771
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
772
+ max_idle = nthreads;
773
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
774
+ }
775
+
776
+ static void ecb_cold
777
+ etp_set_idle_timeout (unsigned int seconds)
778
+ {
779
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
780
+ idle_timeout = seconds;
781
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
782
+ }
783
+
784
+ static void ecb_cold
785
+ etp_set_min_parallel (unsigned int nthreads)
786
+ {
787
+ if (wanted < nthreads)
788
+ wanted = nthreads;
789
+ }
790
+
791
+ static void ecb_cold
792
+ etp_set_max_parallel (unsigned int nthreads)
793
+ {
794
+ if (wanted > nthreads)
795
+ wanted = nthreads;
796
+
797
+ while (started > wanted)
798
+ etp_end_thread ();
799
+ }
800
+
801
+ /*****************************************************************************/
802
+
803
+ static void
804
+ grp_try_feed (eio_req *grp)
805
+ {
806
+ while (grp->size < grp->int2 && !EIO_CANCELLED (grp))
807
+ {
808
+ grp->flags &= ~EIO_FLAG_GROUPADD;
809
+
810
+ EIO_FEED (grp);
811
+
812
+ /* stop if no progress has been made */
813
+ if (!(grp->flags & EIO_FLAG_GROUPADD))
814
+ {
815
+ grp->feed = 0;
816
+ break;
817
+ }
818
+ }
819
+ }
820
+
821
+ static int
822
+ grp_dec (eio_req *grp)
823
+ {
824
+ --grp->size;
825
+
826
+ /* call feeder, if applicable */
827
+ grp_try_feed (grp);
828
+
829
+ /* finish, if done */
830
+ if (!grp->size && grp->int1)
831
+ return eio_finish (grp);
832
+ else
833
+ return 0;
834
+ }
835
+
836
+ static void
837
+ eio_destroy (eio_req *req)
838
+ {
839
+ if ((req)->flags & EIO_FLAG_PTR1_FREE) free (req->ptr1);
840
+ if ((req)->flags & EIO_FLAG_PTR2_FREE) free (req->ptr2);
841
+
842
+ EIO_DESTROY (req);
843
+ }
844
+
845
+ static int
846
+ eio_finish (eio_req *req)
847
+ {
848
+ int res = EIO_FINISH (req);
849
+
850
+ if (req->grp)
851
+ {
852
+ int res2;
853
+ eio_req *grp = req->grp;
854
+
855
+ /* unlink request */
856
+ if (req->grp_next) req->grp_next->grp_prev = req->grp_prev;
857
+ if (req->grp_prev) req->grp_prev->grp_next = req->grp_next;
858
+
859
+ if (grp->grp_first == req)
860
+ grp->grp_first = req->grp_next;
861
+
862
+ res2 = grp_dec (grp);
863
+
864
+ if (!res)
865
+ res = res2;
866
+ }
867
+
868
+ eio_destroy (req);
869
+
870
+ return res;
871
+ }
872
+
873
+ void
874
+ eio_grp_cancel (eio_req *grp)
875
+ {
876
+ for (grp = grp->grp_first; grp; grp = grp->grp_next)
877
+ eio_cancel (grp);
878
+ }
879
+
880
+ void
881
+ eio_cancel (eio_req *req)
882
+ {
883
+ etp_cancel (req);
884
+ }
885
+
886
+ void
887
+ eio_submit (eio_req *req)
888
+ {
889
+ etp_submit (req);
890
+ }
891
+
892
+ unsigned int
893
+ eio_nreqs (void)
894
+ {
895
+ return etp_nreqs ();
896
+ }
897
+
898
+ unsigned int
899
+ eio_nready (void)
900
+ {
901
+ return etp_nready ();
902
+ }
903
+
904
+ unsigned int
905
+ eio_npending (void)
906
+ {
907
+ return etp_npending ();
908
+ }
909
+
910
+ unsigned int ecb_cold
911
+ eio_nthreads (void)
912
+ {
913
+ return etp_nthreads ();
914
+ }
915
+
916
+ void ecb_cold
917
+ eio_set_max_poll_time (double nseconds)
918
+ {
919
+ etp_set_max_poll_time (nseconds);
920
+ }
921
+
922
+ void ecb_cold
923
+ eio_set_max_poll_reqs (unsigned int maxreqs)
924
+ {
925
+ etp_set_max_poll_reqs (maxreqs);
926
+ }
927
+
928
+ void ecb_cold
929
+ eio_set_max_idle (unsigned int nthreads)
930
+ {
931
+ etp_set_max_idle (nthreads);
932
+ }
933
+
934
+ void ecb_cold
935
+ eio_set_idle_timeout (unsigned int seconds)
936
+ {
937
+ etp_set_idle_timeout (seconds);
938
+ }
939
+
940
+ void ecb_cold
941
+ eio_set_min_parallel (unsigned int nthreads)
942
+ {
943
+ etp_set_min_parallel (nthreads);
944
+ }
945
+
946
+ void ecb_cold
947
+ eio_set_max_parallel (unsigned int nthreads)
948
+ {
949
+ etp_set_max_parallel (nthreads);
950
+ }
951
+
952
+ int eio_poll (void)
953
+ {
954
+ return etp_poll ();
955
+ }
956
+
957
+ /*****************************************************************************/
958
+ /* work around various missing functions */
959
+
960
+ #if !HAVE_PREADWRITE
961
+ # undef pread
962
+ # undef pwrite
963
+ # define pread eio__pread
964
+ # define pwrite eio__pwrite
965
+
966
+ eio_ssize_t
967
+ eio__pread (int fd, void *buf, size_t count, off_t offset)
968
+ {
969
+ eio_ssize_t res;
970
+ off_t ooffset;
971
+
972
+ X_LOCK (preadwritelock);
973
+ ooffset = lseek (fd, 0, SEEK_CUR);
974
+ lseek (fd, offset, SEEK_SET);
975
+ res = read (fd, buf, count);
976
+ lseek (fd, ooffset, SEEK_SET);
977
+ X_UNLOCK (preadwritelock);
978
+
979
+ return res;
980
+ }
981
+
982
+ eio_ssize_t
983
+ eio__pwrite (int fd, void *buf, size_t count, off_t offset)
984
+ {
985
+ eio_ssize_t res;
986
+ off_t ooffset;
987
+
988
+ X_LOCK (preadwritelock);
989
+ ooffset = lseek (fd, 0, SEEK_CUR);
990
+ lseek (fd, offset, SEEK_SET);
991
+ res = write (fd, buf, count);
992
+ lseek (fd, ooffset, SEEK_SET);
993
+ X_UNLOCK (preadwritelock);
994
+
995
+ return res;
996
+ }
997
+ #endif
998
+
999
+ #ifndef HAVE_UTIMES
1000
+
1001
+ # undef utimes
1002
+ # define utimes(path,times) eio__utimes (path, times)
1003
+
1004
+ static int
1005
+ eio__utimes (const char *filename, const struct timeval times[2])
1006
+ {
1007
+ if (times)
1008
+ {
1009
+ struct utimbuf buf;
1010
+
1011
+ buf.actime = times[0].tv_sec;
1012
+ buf.modtime = times[1].tv_sec;
1013
+
1014
+ return utime (filename, &buf);
1015
+ }
1016
+ else
1017
+ return utime (filename, 0);
1018
+ }
1019
+
1020
+ #endif
1021
+
1022
+ #ifndef HAVE_FUTIMES
1023
+
1024
+ # undef futimes
1025
+ # define futimes(fd,times) eio__futimes (fd, times)
1026
+
1027
+ static int
1028
+ eio__futimes (int fd, const struct timeval tv[2])
1029
+ {
1030
+ errno = ENOSYS;
1031
+ return -1;
1032
+ }
1033
+
1034
+ #endif
1035
+
1036
+ #if !HAVE_FDATASYNC
1037
+ # undef fdatasync
1038
+ # define fdatasync(fd) fsync (fd)
1039
+ #endif
1040
+
1041
+ static int
1042
+ eio__syncfs (int fd)
1043
+ {
1044
+ int res;
1045
+
1046
+ #if HAVE_SYS_SYNCFS
1047
+ res = (int)syscall (__NR_syncfs, (int)(fd));
1048
+ #else
1049
+ res = -1;
1050
+ errno = ENOSYS;
1051
+ #endif
1052
+
1053
+ if (res < 0 && errno == ENOSYS && fd >= 0)
1054
+ sync ();
1055
+
1056
+ return res;
1057
+ }
1058
+
1059
+ /* sync_file_range always needs emulation */
1060
+ static int
1061
+ eio__sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags)
1062
+ {
1063
+ #if HAVE_SYNC_FILE_RANGE
1064
+ int res;
1065
+
1066
+ if (EIO_SYNC_FILE_RANGE_WAIT_BEFORE != SYNC_FILE_RANGE_WAIT_BEFORE
1067
+ || EIO_SYNC_FILE_RANGE_WRITE != SYNC_FILE_RANGE_WRITE
1068
+ || EIO_SYNC_FILE_RANGE_WAIT_AFTER != SYNC_FILE_RANGE_WAIT_AFTER)
1069
+ {
1070
+ flags = 0
1071
+ | (flags & EIO_SYNC_FILE_RANGE_WAIT_BEFORE ? SYNC_FILE_RANGE_WAIT_BEFORE : 0)
1072
+ | (flags & EIO_SYNC_FILE_RANGE_WRITE ? SYNC_FILE_RANGE_WRITE : 0)
1073
+ | (flags & EIO_SYNC_FILE_RANGE_WAIT_AFTER ? SYNC_FILE_RANGE_WAIT_AFTER : 0);
1074
+ }
1075
+
1076
+ res = sync_file_range (fd, offset, nbytes, flags);
1077
+
1078
+ if (!res || errno != ENOSYS)
1079
+ return res;
1080
+ #endif
1081
+
1082
+ /* even though we could play tricks with the flags, it's better to always
1083
+ * call fdatasync, as that matches the expectation of its users best */
1084
+ return fdatasync (fd);
1085
+ }
1086
+
1087
+ static int
1088
+ eio__fallocate (int fd, int mode, off_t offset, size_t len)
1089
+ {
1090
+ #if HAVE_FALLOCATE
1091
+ return fallocate (fd, mode, offset, len);
1092
+ #else
1093
+ errno = ENOSYS;
1094
+ return -1;
1095
+ #endif
1096
+ }
1097
+
1098
+ #if !HAVE_READAHEAD
1099
+ # undef readahead
1100
+ # define readahead(fd,offset,count) eio__readahead (fd, offset, count, self)
1101
+
1102
+ static eio_ssize_t
1103
+ eio__readahead (int fd, off_t offset, size_t count, etp_worker *self)
1104
+ {
1105
+ size_t todo = count;
1106
+ dBUF;
1107
+
1108
+ while (todo > 0)
1109
+ {
1110
+ size_t len = todo < EIO_BUFSIZE ? todo : EIO_BUFSIZE;
1111
+
1112
+ pread (fd, eio_buf, len, offset);
1113
+ offset += len;
1114
+ todo -= len;
1115
+ }
1116
+
1117
+ FUBd;
1118
+
1119
+ errno = 0;
1120
+ return count;
1121
+ }
1122
+
1123
+ #endif
1124
+
1125
+ /* sendfile always needs emulation */
1126
+ static eio_ssize_t
1127
+ eio__sendfile (int ofd, int ifd, off_t offset, size_t count)
1128
+ {
1129
+ eio_ssize_t written = 0;
1130
+ eio_ssize_t res;
1131
+
1132
+ if (!count)
1133
+ return 0;
1134
+
1135
+ for (;;)
1136
+ {
1137
+ #ifdef __APPLE__
1138
+ # undef HAVE_SENDFILE /* broken, as everything on os x */
1139
+ #endif
1140
+ #if HAVE_SENDFILE
1141
+ # if __linux
1142
+ off_t soffset = offset;
1143
+ res = sendfile (ofd, ifd, &soffset, count);
1144
+
1145
+ # elif __FreeBSD__
1146
+ /*
1147
+ * Of course, the freebsd sendfile is a dire hack with no thoughts
1148
+ * wasted on making it similar to other I/O functions.
1149
+ */
1150
+ off_t sbytes;
1151
+ res = sendfile (ifd, ofd, offset, count, 0, &sbytes, 0);
1152
+
1153
+ #if 0 /* according to the manpage, this is correct, but broken behaviour */
1154
+ /* freebsd' sendfile will return 0 on success */
1155
+ /* freebsd 8 documents it as only setting *sbytes on EINTR and EAGAIN, but */
1156
+ /* not on e.g. EIO or EPIPE - sounds broken */
1157
+ if ((res < 0 && (errno == EAGAIN || errno == EINTR) && sbytes) || res == 0)
1158
+ res = sbytes;
1159
+ #endif
1160
+
1161
+ /* according to source inspection, this is correct, and useful behaviour */
1162
+ if (sbytes)
1163
+ res = sbytes;
1164
+
1165
+ # elif defined (__APPLE__)
1166
+ off_t sbytes = count;
1167
+ res = sendfile (ifd, ofd, offset, &sbytes, 0, 0);
1168
+
1169
+ /* according to the manpage, sbytes is always valid */
1170
+ if (sbytes)
1171
+ res = sbytes;
1172
+
1173
+ # elif __hpux
1174
+ res = sendfile (ofd, ifd, offset, count, 0, 0);
1175
+
1176
+ # elif __solaris
1177
+ struct sendfilevec vec;
1178
+ size_t sbytes;
1179
+
1180
+ vec.sfv_fd = ifd;
1181
+ vec.sfv_flag = 0;
1182
+ vec.sfv_off = offset;
1183
+ vec.sfv_len = count;
1184
+
1185
+ res = sendfilev (ofd, &vec, 1, &sbytes);
1186
+
1187
+ if (res < 0 && sbytes)
1188
+ res = sbytes;
1189
+
1190
+ # endif
1191
+
1192
+ #elif defined (_WIN32) && 0
1193
+ /* does not work, just for documentation of what would need to be done */
1194
+ /* actually, cannot be done like this, as TransmitFile changes the file offset, */
1195
+ /* libeio guarantees that the file offset does not change, and windows */
1196
+ /* has no way to get an independent handle to the same file description */
1197
+ HANDLE h = TO_SOCKET (ifd);
1198
+ SetFilePointer (h, offset, 0, FILE_BEGIN);
1199
+ res = TransmitFile (TO_SOCKET (ofd), h, count, 0, 0, 0, 0);
1200
+
1201
+ #else
1202
+ res = -1;
1203
+ errno = ENOSYS;
1204
+ #endif
1205
+
1206
+ /* we assume sendfile can copy at least 128mb in one go */
1207
+ if (res <= 128 * 1024 * 1024)
1208
+ {
1209
+ if (res > 0)
1210
+ written += res;
1211
+
1212
+ if (written)
1213
+ return written;
1214
+
1215
+ break;
1216
+ }
1217
+ else
1218
+ {
1219
+ /* if we requested more, then probably the kernel was lazy */
1220
+ written += res;
1221
+ offset += res;
1222
+ count -= res;
1223
+
1224
+ if (!count)
1225
+ return written;
1226
+ }
1227
+ }
1228
+
1229
+ if (res < 0
1230
+ && (errno == ENOSYS || errno == EINVAL || errno == ENOTSOCK
1231
+ /* BSDs */
1232
+ #ifdef ENOTSUP /* sigh, if the steenking pile called openbsd would only try to at least compile posix code... */
1233
+ || errno == ENOTSUP
1234
+ #endif
1235
+ #ifdef EOPNOTSUPP /* windows */
1236
+ || errno == EOPNOTSUPP /* BSDs */
1237
+ #endif
1238
+ #if __solaris
1239
+ || errno == EAFNOSUPPORT || errno == EPROTOTYPE
1240
+ #endif
1241
+ )
1242
+ )
1243
+ {
1244
+ /* emulate sendfile. this is a major pain in the ass */
1245
+ dBUF;
1246
+
1247
+ res = 0;
1248
+
1249
+ while (count)
1250
+ {
1251
+ eio_ssize_t cnt;
1252
+
1253
+ cnt = pread (ifd, eio_buf, count > EIO_BUFSIZE ? EIO_BUFSIZE : count, offset);
1254
+
1255
+ if (cnt <= 0)
1256
+ {
1257
+ if (cnt && !res) res = -1;
1258
+ break;
1259
+ }
1260
+
1261
+ cnt = write (ofd, eio_buf, cnt);
1262
+
1263
+ if (cnt <= 0)
1264
+ {
1265
+ if (cnt && !res) res = -1;
1266
+ break;
1267
+ }
1268
+
1269
+ offset += cnt;
1270
+ res += cnt;
1271
+ count -= cnt;
1272
+ }
1273
+
1274
+ FUBd;
1275
+ }
1276
+
1277
+ return res;
1278
+ }
1279
+
1280
+ #ifdef PAGESIZE
1281
+ # define eio_pagesize() PAGESIZE
1282
+ #else
1283
+ static intptr_t
1284
+ eio_pagesize (void)
1285
+ {
1286
+ static intptr_t page;
1287
+
1288
+ if (!page)
1289
+ page = sysconf (_SC_PAGESIZE);
1290
+
1291
+ return page;
1292
+ }
1293
+ #endif
1294
+
1295
+ static void
1296
+ eio_page_align (void **addr, size_t *length)
1297
+ {
1298
+ intptr_t mask = eio_pagesize () - 1;
1299
+
1300
+ /* round down addr */
1301
+ intptr_t adj = mask & (intptr_t)*addr;
1302
+
1303
+ *addr = (void *)((intptr_t)*addr - adj);
1304
+ *length += adj;
1305
+
1306
+ /* round up length */
1307
+ *length = (*length + mask) & ~mask;
1308
+ }
1309
+
1310
+ #if !_POSIX_MEMLOCK
1311
+ # define eio__mlockall(a) EIO_ENOSYS ()
1312
+ #else
1313
+
1314
+ static int
1315
+ eio__mlockall (int flags)
1316
+ {
1317
+ #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7
1318
+ extern int mallopt (int, int);
1319
+ mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */
1320
+ #endif
1321
+
1322
+ if (EIO_MCL_CURRENT != MCL_CURRENT
1323
+ || EIO_MCL_FUTURE != MCL_FUTURE)
1324
+ {
1325
+ flags = 0
1326
+ | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0)
1327
+ | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0);
1328
+ }
1329
+
1330
+ return mlockall (flags);
1331
+ }
1332
+ #endif
1333
+
1334
+ #if !_POSIX_MEMLOCK_RANGE
1335
+ # define eio__mlock(a,b) EIO_ENOSYS ()
1336
+ #else
1337
+
1338
+ static int
1339
+ eio__mlock (void *addr, size_t length)
1340
+ {
1341
+ eio_page_align (&addr, &length);
1342
+
1343
+ return mlock (addr, length);
1344
+ }
1345
+
1346
+ #endif
1347
+
1348
+ #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
1349
+ # define eio__msync(a,b,c) EIO_ENOSYS ()
1350
+ #else
1351
+
1352
+ static int
1353
+ eio__msync (void *mem, size_t len, int flags)
1354
+ {
1355
+ eio_page_align (&mem, &len);
1356
+
1357
+ if (EIO_MS_ASYNC != MS_SYNC
1358
+ || EIO_MS_INVALIDATE != MS_INVALIDATE
1359
+ || EIO_MS_SYNC != MS_SYNC)
1360
+ {
1361
+ flags = 0
1362
+ | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0)
1363
+ | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0)
1364
+ | (flags & EIO_MS_SYNC ? MS_SYNC : 0);
1365
+ }
1366
+
1367
+ return msync (mem, len, flags);
1368
+ }
1369
+
1370
+ #endif
1371
+
1372
+ static int
1373
+ eio__mtouch (eio_req *req)
1374
+ {
1375
+ void *mem = req->ptr2;
1376
+ size_t len = req->size;
1377
+ int flags = req->int1;
1378
+
1379
+ eio_page_align (&mem, &len);
1380
+
1381
+ {
1382
+ intptr_t addr = (intptr_t)mem;
1383
+ intptr_t end = addr + len;
1384
+ intptr_t page = eio_pagesize ();
1385
+
1386
+ if (addr < end)
1387
+ if (flags & EIO_MT_MODIFY) /* modify */
1388
+ do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req));
1389
+ else
1390
+ do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req));
1391
+ }
1392
+
1393
+ return 0;
1394
+ }
1395
+
1396
+ /*****************************************************************************/
1397
+ /* requests implemented outside eio_execute, because they are so large */
1398
+
1399
+ static void
1400
+ eio__realpath (eio_req *req, etp_worker *self)
1401
+ {
1402
+ char *rel = req->ptr1;
1403
+ char *res;
1404
+ char *tmp1, *tmp2;
1405
+ #if SYMLOOP_MAX > 32
1406
+ int symlinks = SYMLOOP_MAX;
1407
+ #else
1408
+ int symlinks = 32;
1409
+ #endif
1410
+
1411
+ req->result = -1;
1412
+
1413
+ errno = EINVAL;
1414
+ if (!rel)
1415
+ return;
1416
+
1417
+ errno = ENOENT;
1418
+ if (!*rel)
1419
+ return;
1420
+
1421
+ if (!req->ptr2)
1422
+ {
1423
+ X_LOCK (wrklock);
1424
+ req->flags |= EIO_FLAG_PTR2_FREE;
1425
+ X_UNLOCK (wrklock);
1426
+ req->ptr2 = malloc (PATH_MAX * 3);
1427
+
1428
+ errno = ENOMEM;
1429
+ if (!req->ptr2)
1430
+ return;
1431
+ }
1432
+
1433
+ res = req->ptr2;
1434
+ tmp1 = res + PATH_MAX;
1435
+ tmp2 = tmp1 + PATH_MAX;
1436
+
1437
+ #if 0 /* disabled, the musl way to do things is just too racy */
1438
+ #if __linux && defined(O_NONBLOCK) && defined(O_NOATIME)
1439
+ /* on linux we may be able to ask the kernel */
1440
+ {
1441
+ int fd = open (rel, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOATIME);
1442
+
1443
+ if (fd >= 0)
1444
+ {
1445
+ sprintf (tmp1, "/proc/self/fd/%d", fd);
1446
+ req->result = readlink (tmp1, res, PATH_MAX);
1447
+ close (fd);
1448
+
1449
+ /* here we should probably stat the open file and the disk file, to make sure they still match */
1450
+
1451
+ if (req->result > 0)
1452
+ goto done;
1453
+ }
1454
+ else if (errno == ELOOP || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EIO)
1455
+ return;
1456
+ }
1457
+ #endif
1458
+ #endif
1459
+
1460
+ if (*rel != '/')
1461
+ {
1462
+ if (!getcwd (res, PATH_MAX))
1463
+ return;
1464
+
1465
+ if (res [1]) /* only use if not / */
1466
+ res += strlen (res);
1467
+ }
1468
+
1469
+ while (*rel)
1470
+ {
1471
+ eio_ssize_t len, linklen;
1472
+ char *beg = rel;
1473
+
1474
+ while (*rel && *rel != '/')
1475
+ ++rel;
1476
+
1477
+ len = rel - beg;
1478
+
1479
+ if (!len) /* skip slashes */
1480
+ {
1481
+ ++rel;
1482
+ continue;
1483
+ }
1484
+
1485
+ if (beg [0] == '.')
1486
+ {
1487
+ if (len == 1)
1488
+ continue; /* . - nop */
1489
+
1490
+ if (beg [1] == '.' && len == 2)
1491
+ {
1492
+ /* .. - back up one component, if possible */
1493
+
1494
+ while (res != req->ptr2)
1495
+ if (*--res == '/')
1496
+ break;
1497
+
1498
+ continue;
1499
+ }
1500
+ }
1501
+
1502
+ errno = ENAMETOOLONG;
1503
+ if (res + 1 + len + 1 >= tmp1)
1504
+ return;
1505
+
1506
+ /* copy one component */
1507
+ *res = '/';
1508
+ memcpy (res + 1, beg, len);
1509
+
1510
+ /* zero-terminate, for readlink */
1511
+ res [len + 1] = 0;
1512
+
1513
+ /* now check if it's a symlink */
1514
+ linklen = readlink (req->ptr2, tmp1, PATH_MAX);
1515
+
1516
+ if (linklen < 0)
1517
+ {
1518
+ if (errno != EINVAL)
1519
+ return;
1520
+
1521
+ /* it's a normal directory. hopefully */
1522
+ res += len + 1;
1523
+ }
1524
+ else
1525
+ {
1526
+ /* yay, it was a symlink - build new path in tmp2 */
1527
+ int rellen = strlen (rel);
1528
+
1529
+ errno = ENAMETOOLONG;
1530
+ if (linklen + 1 + rellen >= PATH_MAX)
1531
+ return;
1532
+
1533
+ errno = ELOOP;
1534
+ if (!--symlinks)
1535
+ return;
1536
+
1537
+ if (*tmp1 == '/')
1538
+ res = req->ptr2; /* symlink resolves to an absolute path */
1539
+
1540
+ /* we need to be careful, as rel might point into tmp2 already */
1541
+ memmove (tmp2 + linklen + 1, rel, rellen + 1);
1542
+ tmp2 [linklen] = '/';
1543
+ memcpy (tmp2, tmp1, linklen);
1544
+
1545
+ rel = tmp2;
1546
+ }
1547
+ }
1548
+
1549
+ /* special case for the lone root path */
1550
+ if (res == req->ptr2)
1551
+ *res++ = '/';
1552
+
1553
+ req->result = res - (char *)req->ptr2;
1554
+
1555
+ done:
1556
+ req->ptr2 = realloc (req->ptr2, req->result); /* trade time for space savings */
1557
+ }
1558
+
1559
+ static signed char
1560
+ eio_dent_cmp (const eio_dirent *a, const eio_dirent *b)
1561
+ {
1562
+ return a->score - b->score ? a->score - b->score /* works because our signed char is always 0..100 */
1563
+ : a->inode < b->inode ? -1
1564
+ : a->inode > b->inode ? 1
1565
+ : 0;
1566
+ }
1567
+
1568
+ #define EIO_DENT_CMP(i,op,j) eio_dent_cmp (&i, &j) op 0
1569
+
1570
+ #define EIO_SORT_CUTOFF 30 /* quite high, but performs well on many filesystems */
1571
+ #define EIO_SORT_FAST 60 /* when to only use insertion sort */
1572
+
1573
+ static void
1574
+ eio_dent_radix_sort (eio_dirent *dents, int size, signed char score_bits, eio_ino_t inode_bits)
1575
+ {
1576
+ unsigned char bits [9 + sizeof (eio_ino_t) * 8];
1577
+ unsigned char *bit = bits;
1578
+
1579
+ assert (CHAR_BIT == 8);
1580
+ assert (sizeof (eio_dirent) * 8 < 256);
1581
+ assert (offsetof (eio_dirent, inode)); /* we use bit #0 as sentinel */
1582
+ assert (offsetof (eio_dirent, score)); /* we use bit #0 as sentinel */
1583
+
1584
+ if (size <= EIO_SORT_FAST)
1585
+ return;
1586
+
1587
+ /* first prepare an array of bits to test in our radix sort */
1588
+ /* try to take endianness into account, as well as differences in eio_ino_t sizes */
1589
+ /* inode_bits must contain all inodes ORed together */
1590
+ /* which is used to skip bits that are 0 everywhere, which is very common */
1591
+ {
1592
+ eio_ino_t endianness;
1593
+ int i, j;
1594
+
1595
+ /* we store the byte offset of byte n into byte n of "endianness" */
1596
+ for (i = 0; i < sizeof (eio_ino_t); ++i)
1597
+ ((unsigned char *)&endianness)[i] = i;
1598
+
1599
+ *bit++ = 0;
1600
+
1601
+ for (i = 0; i < sizeof (eio_ino_t); ++i)
1602
+ {
1603
+ /* shifting off the byte offsets out of "endianness" */
1604
+ int offs = (offsetof (eio_dirent, inode) + (endianness & 0xff)) * 8;
1605
+ endianness >>= 8;
1606
+
1607
+ for (j = 0; j < 8; ++j)
1608
+ if (inode_bits & (((eio_ino_t)1) << (i * 8 + j)))
1609
+ *bit++ = offs + j;
1610
+ }
1611
+
1612
+ for (j = 0; j < 8; ++j)
1613
+ if (score_bits & (1 << j))
1614
+ *bit++ = offsetof (eio_dirent, score) * 8 + j;
1615
+ }
1616
+
1617
+ /* now actually do the sorting (a variant of MSD radix sort) */
1618
+ {
1619
+ eio_dirent *base_stk [9 + sizeof (eio_ino_t) * 8], *base;
1620
+ eio_dirent *end_stk [9 + sizeof (eio_ino_t) * 8], *end;
1621
+ unsigned char *bit_stk [9 + sizeof (eio_ino_t) * 8];
1622
+ int stk_idx = 0;
1623
+
1624
+ base_stk [stk_idx] = dents;
1625
+ end_stk [stk_idx] = dents + size;
1626
+ bit_stk [stk_idx] = bit - 1;
1627
+
1628
+ do
1629
+ {
1630
+ base = base_stk [stk_idx];
1631
+ end = end_stk [stk_idx];
1632
+ bit = bit_stk [stk_idx];
1633
+
1634
+ for (;;)
1635
+ {
1636
+ unsigned char O = *bit >> 3;
1637
+ unsigned char M = 1 << (*bit & 7);
1638
+
1639
+ eio_dirent *a = base;
1640
+ eio_dirent *b = end;
1641
+
1642
+ if (b - a < EIO_SORT_CUTOFF)
1643
+ break;
1644
+
1645
+ /* now bit-partition the array on the bit */
1646
+ /* this ugly asymmetric loop seems to perform much better than typical */
1647
+ /* partition algos found in the literature */
1648
+ do
1649
+ if (!(((unsigned char *)a)[O] & M))
1650
+ ++a;
1651
+ else if (!(((unsigned char *)--b)[O] & M))
1652
+ {
1653
+ eio_dirent tmp = *a; *a = *b; *b = tmp;
1654
+ ++a;
1655
+ }
1656
+ while (b > a);
1657
+
1658
+ /* next bit, or stop, if no bits left in this path */
1659
+ if (!*--bit)
1660
+ break;
1661
+
1662
+ base_stk [stk_idx] = a;
1663
+ end_stk [stk_idx] = end;
1664
+ bit_stk [stk_idx] = bit;
1665
+ ++stk_idx;
1666
+
1667
+ end = a;
1668
+ }
1669
+ }
1670
+ while (stk_idx--);
1671
+ }
1672
+ }
1673
+
1674
+ static void
1675
+ eio_dent_insertion_sort (eio_dirent *dents, int size)
1676
+ {
1677
+ /* first move the smallest element to the front, to act as a sentinel */
1678
+ {
1679
+ int i;
1680
+ eio_dirent *min = dents;
1681
+
1682
+ /* the radix pre-pass ensures that the minimum element is in the first EIO_SORT_CUTOFF + 1 elements */
1683
+ for (i = size > EIO_SORT_FAST ? EIO_SORT_CUTOFF + 1 : size; --i; )
1684
+ if (EIO_DENT_CMP (dents [i], <, *min))
1685
+ min = &dents [i];
1686
+
1687
+ /* swap elements 0 and j (minimum) */
1688
+ {
1689
+ eio_dirent tmp = *dents; *dents = *min; *min = tmp;
1690
+ }
1691
+ }
1692
+
1693
+ /* then do standard insertion sort, assuming that all elements are >= dents [0] */
1694
+ {
1695
+ eio_dirent *i, *j;
1696
+
1697
+ for (i = dents + 1; i < dents + size; ++i)
1698
+ {
1699
+ eio_dirent value = *i;
1700
+
1701
+ for (j = i - 1; EIO_DENT_CMP (*j, >, value); --j)
1702
+ j [1] = j [0];
1703
+
1704
+ j [1] = value;
1705
+ }
1706
+ }
1707
+ }
1708
+
1709
+ static void
1710
+ eio_dent_sort (eio_dirent *dents, int size, signed char score_bits, eio_ino_t inode_bits)
1711
+ {
1712
+ if (size <= 1)
1713
+ return; /* our insertion sort relies on size > 0 */
1714
+
1715
+ /* first we use a radix sort, but only for dirs >= EIO_SORT_FAST */
1716
+ /* and stop sorting when the partitions are <= EIO_SORT_CUTOFF */
1717
+ eio_dent_radix_sort (dents, size, score_bits, inode_bits);
1718
+
1719
+ /* use an insertion sort at the end, or for small arrays, */
1720
+ /* as insertion sort is more efficient for small partitions */
1721
+ eio_dent_insertion_sort (dents, size);
1722
+ }
1723
+
1724
+ /* read a full directory */
1725
+ static void
1726
+ eio__scandir (eio_req *req, etp_worker *self)
1727
+ {
1728
+ char *name, *names;
1729
+ int namesalloc = 4096 - sizeof (void *) * 4;
1730
+ int namesoffs = 0;
1731
+ int flags = req->int1;
1732
+ eio_dirent *dents = 0;
1733
+ int dentalloc = 128;
1734
+ int dentoffs = 0;
1735
+ eio_ino_t inode_bits = 0;
1736
+ #ifdef _WIN32
1737
+ HANDLE dirp;
1738
+ WIN32_FIND_DATA entp;
1739
+ #else
1740
+ DIR *dirp;
1741
+ EIO_STRUCT_DIRENT *entp;
1742
+ #endif
1743
+
1744
+ req->result = -1;
1745
+
1746
+ if (!(flags & EIO_READDIR_DENTS))
1747
+ flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER);
1748
+
1749
+ #ifdef _WIN32
1750
+ {
1751
+ int len = strlen ((const char *)req->ptr1);
1752
+ char *path = malloc (MAX_PATH);
1753
+ const char *fmt;
1754
+
1755
+ if (!len)
1756
+ fmt = "./*";
1757
+ else if (((const char *)req->ptr1)[len - 1] == '/' || ((const char *)req->ptr1)[len - 1] == '\\')
1758
+ fmt = "%s*";
1759
+ else
1760
+ fmt = "%s/*";
1761
+
1762
+ _snprintf (path, MAX_PATH, fmt, (const char *)req->ptr1);
1763
+ dirp = FindFirstFile (path, &entp);
1764
+ free (path);
1765
+
1766
+ if (dirp == INVALID_HANDLE_VALUE)
1767
+ {
1768
+ dirp = 0;
1769
+
1770
+ /* should steal _dosmaperr */
1771
+ switch (GetLastError ())
1772
+ {
1773
+ case ERROR_FILE_NOT_FOUND:
1774
+ req->result = 0;
1775
+ break;
1776
+
1777
+ case ERROR_INVALID_NAME:
1778
+ case ERROR_PATH_NOT_FOUND:
1779
+ case ERROR_NO_MORE_FILES:
1780
+ errno = ENOENT;
1781
+ break;
1782
+
1783
+ case ERROR_NOT_ENOUGH_MEMORY:
1784
+ errno = ENOMEM;
1785
+ break;
1786
+
1787
+ default:
1788
+ errno = EINVAL;
1789
+ break;
1790
+ }
1791
+ }
1792
+ }
1793
+ #else
1794
+ dirp = opendir (req->ptr1);
1795
+ #endif
1796
+
1797
+ if (req->flags & EIO_FLAG_PTR1_FREE)
1798
+ free (req->ptr1);
1799
+
1800
+ req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE;
1801
+ req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0;
1802
+ req->ptr2 = names = malloc (namesalloc);
1803
+
1804
+ if (dirp && names && (!flags || dents))
1805
+ for (;;)
1806
+ {
1807
+ int done;
1808
+
1809
+ #ifdef _WIN32
1810
+ done = !dirp;
1811
+ #else
1812
+ errno = 0;
1813
+ entp = readdir (dirp);
1814
+ done = !entp;
1815
+ #endif
1816
+
1817
+ if (done)
1818
+ {
1819
+ #ifndef _WIN32
1820
+ int old_errno = errno;
1821
+ closedir (dirp);
1822
+ errno = old_errno;
1823
+
1824
+ if (errno)
1825
+ break;
1826
+ #endif
1827
+
1828
+ /* sort etc. */
1829
+ req->int1 = flags;
1830
+ req->result = dentoffs;
1831
+
1832
+ if (flags & EIO_READDIR_STAT_ORDER)
1833
+ eio_dent_sort (dents, dentoffs, flags & EIO_READDIR_DIRS_FIRST ? 7 : 0, inode_bits);
1834
+ else if (flags & EIO_READDIR_DIRS_FIRST)
1835
+ if (flags & EIO_READDIR_FOUND_UNKNOWN)
1836
+ eio_dent_sort (dents, dentoffs, 7, inode_bits); /* sort by score and inode */
1837
+ else
1838
+ {
1839
+ /* in this case, all is known, and we just put dirs first and sort them */
1840
+ eio_dirent *oth = dents + dentoffs;
1841
+ eio_dirent *dir = dents;
1842
+
1843
+ /* now partition dirs to the front, and non-dirs to the back */
1844
+ /* by walking from both sides and swapping if necessary */
1845
+ while (oth > dir)
1846
+ {
1847
+ if (dir->type == EIO_DT_DIR)
1848
+ ++dir;
1849
+ else if ((--oth)->type == EIO_DT_DIR)
1850
+ {
1851
+ eio_dirent tmp = *dir; *dir = *oth; *oth = tmp;
1852
+
1853
+ ++dir;
1854
+ }
1855
+ }
1856
+
1857
+ /* now sort the dirs only (dirs all have the same score) */
1858
+ eio_dent_sort (dents, dir - dents, 0, inode_bits);
1859
+ }
1860
+
1861
+ break;
1862
+ }
1863
+
1864
+ /* now add the entry to our list(s) */
1865
+ name = D_NAME (entp);
1866
+
1867
+ /* skip . and .. entries */
1868
+ if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2])))
1869
+ {
1870
+ int len = D_NAMLEN (entp) + 1;
1871
+
1872
+ while (ecb_expect_false (namesoffs + len > namesalloc))
1873
+ {
1874
+ namesalloc *= 2;
1875
+ req->ptr2 = names = realloc (names, namesalloc);
1876
+
1877
+ if (!names)
1878
+ break;
1879
+ }
1880
+
1881
+ memcpy (names + namesoffs, name, len);
1882
+
1883
+ if (dents)
1884
+ {
1885
+ struct eio_dirent *ent;
1886
+
1887
+ if (ecb_expect_false (dentoffs == dentalloc))
1888
+ {
1889
+ dentalloc *= 2;
1890
+ req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent));
1891
+
1892
+ if (!dents)
1893
+ break;
1894
+ }
1895
+
1896
+ ent = dents + dentoffs;
1897
+
1898
+ ent->nameofs = namesoffs; /* rather dirtily we store the offset in the pointer */
1899
+ ent->namelen = len - 1;
1900
+ ent->inode = D_INO (entp);
1901
+
1902
+ inode_bits |= ent->inode;
1903
+
1904
+ switch (D_TYPE (entp))
1905
+ {
1906
+ default:
1907
+ ent->type = EIO_DT_UNKNOWN;
1908
+ flags |= EIO_READDIR_FOUND_UNKNOWN;
1909
+ break;
1910
+
1911
+ #ifdef DT_FIFO
1912
+ case DT_FIFO: ent->type = EIO_DT_FIFO; break;
1913
+ #endif
1914
+ #ifdef DT_CHR
1915
+ case DT_CHR: ent->type = EIO_DT_CHR; break;
1916
+ #endif
1917
+ #ifdef DT_MPC
1918
+ case DT_MPC: ent->type = EIO_DT_MPC; break;
1919
+ #endif
1920
+ #ifdef DT_DIR
1921
+ case DT_DIR: ent->type = EIO_DT_DIR; break;
1922
+ #endif
1923
+ #ifdef DT_NAM
1924
+ case DT_NAM: ent->type = EIO_DT_NAM; break;
1925
+ #endif
1926
+ #ifdef DT_BLK
1927
+ case DT_BLK: ent->type = EIO_DT_BLK; break;
1928
+ #endif
1929
+ #ifdef DT_MPB
1930
+ case DT_MPB: ent->type = EIO_DT_MPB; break;
1931
+ #endif
1932
+ #ifdef DT_REG
1933
+ case DT_REG: ent->type = EIO_DT_REG; break;
1934
+ #endif
1935
+ #ifdef DT_NWK
1936
+ case DT_NWK: ent->type = EIO_DT_NWK; break;
1937
+ #endif
1938
+ #ifdef DT_CMP
1939
+ case DT_CMP: ent->type = EIO_DT_CMP; break;
1940
+ #endif
1941
+ #ifdef DT_LNK
1942
+ case DT_LNK: ent->type = EIO_DT_LNK; break;
1943
+ #endif
1944
+ #ifdef DT_SOCK
1945
+ case DT_SOCK: ent->type = EIO_DT_SOCK; break;
1946
+ #endif
1947
+ #ifdef DT_DOOR
1948
+ case DT_DOOR: ent->type = EIO_DT_DOOR; break;
1949
+ #endif
1950
+ #ifdef DT_WHT
1951
+ case DT_WHT: ent->type = EIO_DT_WHT; break;
1952
+ #endif
1953
+ }
1954
+
1955
+ ent->score = 7;
1956
+
1957
+ if (flags & EIO_READDIR_DIRS_FIRST)
1958
+ {
1959
+ if (ent->type == EIO_DT_UNKNOWN)
1960
+ {
1961
+ if (*name == '.') /* leading dots are likely directories, and, in any case, rare */
1962
+ ent->score = 1;
1963
+ else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */
1964
+ ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */
1965
+ }
1966
+ else if (ent->type == EIO_DT_DIR)
1967
+ ent->score = 0;
1968
+ }
1969
+ }
1970
+
1971
+ namesoffs += len;
1972
+ ++dentoffs;
1973
+ }
1974
+
1975
+ if (EIO_CANCELLED (req))
1976
+ {
1977
+ errno = ECANCELED;
1978
+ break;
1979
+ }
1980
+
1981
+ #ifdef _WIN32
1982
+ if (!FindNextFile (dirp, &entp))
1983
+ {
1984
+ FindClose (dirp);
1985
+ dirp = 0;
1986
+ }
1987
+ #endif
1988
+ }
1989
+ }
1990
+
1991
+ /*****************************************************************************/
1992
+
1993
+ #define ALLOC(len) \
1994
+ if (!req->ptr2) \
1995
+ { \
1996
+ X_LOCK (wrklock); \
1997
+ req->flags |= EIO_FLAG_PTR2_FREE; \
1998
+ X_UNLOCK (wrklock); \
1999
+ req->ptr2 = malloc (len); \
2000
+ if (!req->ptr2) \
2001
+ { \
2002
+ errno = ENOMEM; \
2003
+ req->result = -1; \
2004
+ break; \
2005
+ } \
2006
+ }
2007
+
2008
+ X_THREAD_PROC (etp_proc)
2009
+ {
2010
+ ETP_REQ *req;
2011
+ struct timespec ts;
2012
+ etp_worker *self = (etp_worker *)thr_arg;
2013
+
2014
+ #if HAVE_PRCTL_SET_NAME
2015
+ prctl (PR_SET_NAME, (unsigned long)"eio_thread", 0, 0, 0);
2016
+ #endif
2017
+
2018
+ /* try to distribute timeouts somewhat evenly */
2019
+ ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
2020
+
2021
+ for (;;)
2022
+ {
2023
+ ts.tv_sec = 0;
2024
+
2025
+ X_LOCK (reqlock);
2026
+
2027
+ for (;;)
2028
+ {
2029
+ self->req = req = reqq_shift (&req_queue);
2030
+
2031
+ if (req)
2032
+ break;
2033
+
2034
+ if (ts.tv_sec == 1) /* no request, but timeout detected, let's quit */
2035
+ {
2036
+ X_UNLOCK (reqlock);
2037
+ X_LOCK (wrklock);
2038
+ --started;
2039
+ X_UNLOCK (wrklock);
2040
+ goto quit;
2041
+ }
2042
+
2043
+ ++idle;
2044
+
2045
+ if (idle <= max_idle)
2046
+ /* we are allowed to idle, so do so without any timeout */
2047
+ X_COND_WAIT (reqwait, reqlock);
2048
+ else
2049
+ {
2050
+ /* initialise timeout once */
2051
+ if (!ts.tv_sec)
2052
+ ts.tv_sec = time (0) + idle_timeout;
2053
+
2054
+ if (X_COND_TIMEDWAIT (reqwait, reqlock, ts) == ETIMEDOUT)
2055
+ ts.tv_sec = 1; /* assuming this is not a value computed above.,.. */
2056
+ }
2057
+
2058
+ --idle;
2059
+ }
2060
+
2061
+ --nready;
2062
+
2063
+ X_UNLOCK (reqlock);
2064
+
2065
+ if (req->type < 0)
2066
+ goto quit;
2067
+
2068
+ ETP_EXECUTE (self, req);
2069
+
2070
+ X_LOCK (reslock);
2071
+
2072
+ ++npending;
2073
+
2074
+ if (!reqq_push (&res_queue, req) && want_poll_cb)
2075
+ want_poll_cb ();
2076
+
2077
+ self->req = 0;
2078
+ etp_worker_clear (self);
2079
+
2080
+ X_UNLOCK (reslock);
2081
+ }
2082
+
2083
+ quit:
2084
+ X_LOCK (wrklock);
2085
+ etp_worker_free (self);
2086
+ X_UNLOCK (wrklock);
2087
+
2088
+ return 0;
2089
+ }
2090
+
2091
+ /*****************************************************************************/
2092
+
2093
+ int ecb_cold
2094
+ eio_init (void (*want_poll)(void), void (*done_poll)(void))
2095
+ {
2096
+ #if !HAVE_PREADWRITE
2097
+ X_MUTEX_CREATE (preadwritelock);
2098
+ #endif
2099
+
2100
+ return etp_init (want_poll, done_poll);
2101
+ }
2102
+
2103
+ ecb_inline void
2104
+ eio_api_destroy (eio_req *req)
2105
+ {
2106
+ free (req);
2107
+ }
2108
+
2109
+ #define REQ(rtype) \
2110
+ eio_req *req; \
2111
+ \
2112
+ req = (eio_req *)calloc (1, sizeof *req); \
2113
+ if (!req) \
2114
+ return 0; \
2115
+ \
2116
+ req->type = rtype; \
2117
+ req->pri = pri; \
2118
+ req->finish = cb; \
2119
+ req->data = data; \
2120
+ req->destroy = eio_api_destroy;
2121
+
2122
+ #define SEND eio_submit (req); return req
2123
+
2124
+ #define PATH \
2125
+ req->flags |= EIO_FLAG_PTR1_FREE; \
2126
+ req->ptr1 = strdup (path); \
2127
+ if (!req->ptr1) \
2128
+ { \
2129
+ eio_api_destroy (req); \
2130
+ return 0; \
2131
+ }
2132
+
2133
+ static void
2134
+ eio_execute (etp_worker *self, eio_req *req)
2135
+ {
2136
+ if (ecb_expect_false (EIO_CANCELLED (req)))
2137
+ {
2138
+ req->result = -1;
2139
+ req->errorno = ECANCELED;
2140
+ return;
2141
+ }
2142
+
2143
+ switch (req->type)
2144
+ {
2145
+ case EIO_READ: ALLOC (req->size);
2146
+ req->result = req->offs >= 0
2147
+ ? pread (req->int1, req->ptr2, req->size, req->offs)
2148
+ : read (req->int1, req->ptr2, req->size); break;
2149
+ case EIO_WRITE: req->result = req->offs >= 0
2150
+ ? pwrite (req->int1, req->ptr2, req->size, req->offs)
2151
+ : write (req->int1, req->ptr2, req->size); break;
2152
+
2153
+ case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
2154
+ case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break;
2155
+
2156
+ case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2157
+ req->result = stat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
2158
+ case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2159
+ req->result = lstat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
2160
+ case EIO_FSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2161
+ req->result = fstat (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break;
2162
+
2163
+ case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2164
+ req->result = statvfs (req->ptr1, (EIO_STRUCT_STATVFS *)req->ptr2); break;
2165
+ case EIO_FSTATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2166
+ req->result = fstatvfs (req->int1, (EIO_STRUCT_STATVFS *)req->ptr2); break;
2167
+
2168
+ case EIO_CHOWN: req->result = chown (req->ptr1, req->int2, req->int3); break;
2169
+ case EIO_FCHOWN: req->result = fchown (req->int1, req->int2, req->int3); break;
2170
+ case EIO_CHMOD: req->result = chmod (req->ptr1, (eio_mode_t)req->int2); break;
2171
+ case EIO_FCHMOD: req->result = fchmod (req->int1, (eio_mode_t)req->int2); break;
2172
+ case EIO_TRUNCATE: req->result = truncate (req->ptr1, req->offs); break;
2173
+ case EIO_FTRUNCATE: req->result = ftruncate (req->int1, req->offs); break;
2174
+
2175
+ case EIO_OPEN: req->result = open (req->ptr1, req->int1, (eio_mode_t)req->int2); break;
2176
+ case EIO_CLOSE: req->result = close (req->int1); break;
2177
+ case EIO_DUP2: req->result = dup2 (req->int1, req->int2); break;
2178
+ case EIO_UNLINK: req->result = unlink (req->ptr1); break;
2179
+ case EIO_RMDIR: req->result = rmdir (req->ptr1); break;
2180
+ case EIO_MKDIR: req->result = mkdir (req->ptr1, (eio_mode_t)req->int2); break;
2181
+ case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break;
2182
+ case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break;
2183
+ case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break;
2184
+ case EIO_MKNOD: req->result = mknod (req->ptr1, (eio_mode_t)req->int2, (dev_t)req->offs); break;
2185
+
2186
+ case EIO_REALPATH: eio__realpath (req, self); break;
2187
+
2188
+ case EIO_READLINK: ALLOC (PATH_MAX);
2189
+ req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break;
2190
+
2191
+ case EIO_SYNC: req->result = 0; sync (); break;
2192
+ case EIO_FSYNC: req->result = fsync (req->int1); break;
2193
+ case EIO_FDATASYNC: req->result = fdatasync (req->int1); break;
2194
+ case EIO_SYNCFS: req->result = eio__syncfs (req->int1); break;
2195
+ case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
2196
+ case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break;
2197
+ case EIO_MTOUCH: req->result = eio__mtouch (req); break;
2198
+ case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break;
2199
+ case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break;
2200
+ case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break;
2201
+
2202
+ case EIO_READDIR: eio__scandir (req, self); break;
2203
+
2204
+ case EIO_BUSY:
2205
+ #ifdef _WIN32
2206
+ Sleep (req->nv1 * 1e3);
2207
+ #else
2208
+ {
2209
+ struct timeval tv;
2210
+
2211
+ tv.tv_sec = req->nv1;
2212
+ tv.tv_usec = (req->nv1 - tv.tv_sec) * 1e6;
2213
+
2214
+ req->result = select (0, 0, 0, 0, &tv);
2215
+ }
2216
+ #endif
2217
+ break;
2218
+
2219
+ case EIO_UTIME:
2220
+ case EIO_FUTIME:
2221
+ {
2222
+ struct timeval tv[2];
2223
+ struct timeval *times;
2224
+
2225
+ if (req->nv1 != -1. || req->nv2 != -1.)
2226
+ {
2227
+ tv[0].tv_sec = req->nv1;
2228
+ tv[0].tv_usec = (req->nv1 - tv[0].tv_sec) * 1000000.;
2229
+ tv[1].tv_sec = req->nv2;
2230
+ tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1000000.;
2231
+
2232
+ times = tv;
2233
+ }
2234
+ else
2235
+ times = 0;
2236
+
2237
+ req->result = req->type == EIO_FUTIME
2238
+ ? futimes (req->int1, times)
2239
+ : utimes (req->ptr1, times);
2240
+ }
2241
+ break;
2242
+
2243
+ case EIO_GROUP:
2244
+ abort (); /* handled in eio_request */
2245
+
2246
+ case EIO_NOP:
2247
+ req->result = 0;
2248
+ break;
2249
+
2250
+ case EIO_CUSTOM:
2251
+ req->feed (req);
2252
+ break;
2253
+
2254
+ default:
2255
+ errno = ENOSYS;
2256
+ req->result = -1;
2257
+ break;
2258
+ }
2259
+
2260
+ req->errorno = errno;
2261
+ }
2262
+
2263
+ #ifndef EIO_NO_WRAPPERS
2264
+
2265
+ eio_req *eio_nop (int pri, eio_cb cb, void *data)
2266
+ {
2267
+ REQ (EIO_NOP); SEND;
2268
+ }
2269
+
2270
+ eio_req *eio_busy (double delay, int pri, eio_cb cb, void *data)
2271
+ {
2272
+ REQ (EIO_BUSY); req->nv1 = delay; SEND;
2273
+ }
2274
+
2275
+ eio_req *eio_sync (int pri, eio_cb cb, void *data)
2276
+ {
2277
+ REQ (EIO_SYNC); SEND;
2278
+ }
2279
+
2280
+ eio_req *eio_fsync (int fd, int pri, eio_cb cb, void *data)
2281
+ {
2282
+ REQ (EIO_FSYNC); req->int1 = fd; SEND;
2283
+ }
2284
+
2285
+ eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data)
2286
+ {
2287
+ REQ (EIO_MSYNC); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
2288
+ }
2289
+
2290
+ eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data)
2291
+ {
2292
+ REQ (EIO_FDATASYNC); req->int1 = fd; SEND;
2293
+ }
2294
+
2295
+ eio_req *eio_syncfs (int fd, int pri, eio_cb cb, void *data)
2296
+ {
2297
+ REQ (EIO_SYNCFS); req->int1 = fd; SEND;
2298
+ }
2299
+
2300
+ eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data)
2301
+ {
2302
+ REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND;
2303
+ }
2304
+
2305
+ eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data)
2306
+ {
2307
+ REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
2308
+ }
2309
+
2310
+ eio_req *eio_mlock (void *addr, size_t length, int pri, eio_cb cb, void *data)
2311
+ {
2312
+ REQ (EIO_MLOCK); req->ptr2 = addr; req->size = length; SEND;
2313
+ }
2314
+
2315
+ eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data)
2316
+ {
2317
+ REQ (EIO_MLOCKALL); req->int1 = flags; SEND;
2318
+ }
2319
+
2320
+ eio_req *eio_fallocate (int fd, int mode, off_t offset, size_t len, int pri, eio_cb cb, void *data)
2321
+ {
2322
+ REQ (EIO_FALLOCATE); req->int1 = fd; req->int2 = mode; req->offs = offset; req->size = len; SEND;
2323
+ }
2324
+
2325
+ eio_req *eio_close (int fd, int pri, eio_cb cb, void *data)
2326
+ {
2327
+ REQ (EIO_CLOSE); req->int1 = fd; SEND;
2328
+ }
2329
+
2330
+ eio_req *eio_readahead (int fd, off_t offset, size_t length, int pri, eio_cb cb, void *data)
2331
+ {
2332
+ REQ (EIO_READAHEAD); req->int1 = fd; req->offs = offset; req->size = length; SEND;
2333
+ }
2334
+
2335
+ eio_req *eio_read (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data)
2336
+ {
2337
+ REQ (EIO_READ); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = buf; SEND;
2338
+ }
2339
+
2340
+ eio_req *eio_write (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data)
2341
+ {
2342
+ REQ (EIO_WRITE); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = buf; SEND;
2343
+ }
2344
+
2345
+ eio_req *eio_fstat (int fd, int pri, eio_cb cb, void *data)
2346
+ {
2347
+ REQ (EIO_FSTAT); req->int1 = fd; SEND;
2348
+ }
2349
+
2350
+ eio_req *eio_fstatvfs (int fd, int pri, eio_cb cb, void *data)
2351
+ {
2352
+ REQ (EIO_FSTATVFS); req->int1 = fd; SEND;
2353
+ }
2354
+
2355
+ eio_req *eio_futime (int fd, double atime, double mtime, int pri, eio_cb cb, void *data)
2356
+ {
2357
+ REQ (EIO_FUTIME); req->int1 = fd; req->nv1 = atime; req->nv2 = mtime; SEND;
2358
+ }
2359
+
2360
+ eio_req *eio_ftruncate (int fd, off_t offset, int pri, eio_cb cb, void *data)
2361
+ {
2362
+ REQ (EIO_FTRUNCATE); req->int1 = fd; req->offs = offset; SEND;
2363
+ }
2364
+
2365
+ eio_req *eio_fchmod (int fd, eio_mode_t mode, int pri, eio_cb cb, void *data)
2366
+ {
2367
+ REQ (EIO_FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND;
2368
+ }
2369
+
2370
+ eio_req *eio_fchown (int fd, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
2371
+ {
2372
+ REQ (EIO_FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
2373
+ }
2374
+
2375
+ eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data)
2376
+ {
2377
+ REQ (EIO_DUP2); req->int1 = fd; req->int2 = fd2; SEND;
2378
+ }
2379
+
2380
+ eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, int pri, eio_cb cb, void *data)
2381
+ {
2382
+ REQ (EIO_SENDFILE); req->int1 = out_fd; req->int2 = in_fd; req->offs = in_offset; req->size = length; SEND;
2383
+ }
2384
+
2385
+ eio_req *eio_open (const char *path, int flags, eio_mode_t mode, int pri, eio_cb cb, void *data)
2386
+ {
2387
+ REQ (EIO_OPEN); PATH; req->int1 = flags; req->int2 = (long)mode; SEND;
2388
+ }
2389
+
2390
+ eio_req *eio_utime (const char *path, double atime, double mtime, int pri, eio_cb cb, void *data)
2391
+ {
2392
+ REQ (EIO_UTIME); PATH; req->nv1 = atime; req->nv2 = mtime; SEND;
2393
+ }
2394
+
2395
+ eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data)
2396
+ {
2397
+ REQ (EIO_TRUNCATE); PATH; req->offs = offset; SEND;
2398
+ }
2399
+
2400
+ eio_req *eio_chown (const char *path, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
2401
+ {
2402
+ REQ (EIO_CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
2403
+ }
2404
+
2405
+ eio_req *eio_chmod (const char *path, eio_mode_t mode, int pri, eio_cb cb, void *data)
2406
+ {
2407
+ REQ (EIO_CHMOD); PATH; req->int2 = (long)mode; SEND;
2408
+ }
2409
+
2410
+ eio_req *eio_mkdir (const char *path, eio_mode_t mode, int pri, eio_cb cb, void *data)
2411
+ {
2412
+ REQ (EIO_MKDIR); PATH; req->int2 = (long)mode; SEND;
2413
+ }
2414
+
2415
+ static eio_req *
2416
+ eio__1path (int type, const char *path, int pri, eio_cb cb, void *data)
2417
+ {
2418
+ REQ (type); PATH; SEND;
2419
+ }
2420
+
2421
+ eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data)
2422
+ {
2423
+ return eio__1path (EIO_READLINK, path, pri, cb, data);
2424
+ }
2425
+
2426
+ eio_req *eio_realpath (const char *path, int pri, eio_cb cb, void *data)
2427
+ {
2428
+ return eio__1path (EIO_REALPATH, path, pri, cb, data);
2429
+ }
2430
+
2431
+ eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data)
2432
+ {
2433
+ return eio__1path (EIO_STAT, path, pri, cb, data);
2434
+ }
2435
+
2436
+ eio_req *eio_lstat (const char *path, int pri, eio_cb cb, void *data)
2437
+ {
2438
+ return eio__1path (EIO_LSTAT, path, pri, cb, data);
2439
+ }
2440
+
2441
+ eio_req *eio_statvfs (const char *path, int pri, eio_cb cb, void *data)
2442
+ {
2443
+ return eio__1path (EIO_STATVFS, path, pri, cb, data);
2444
+ }
2445
+
2446
+ eio_req *eio_unlink (const char *path, int pri, eio_cb cb, void *data)
2447
+ {
2448
+ return eio__1path (EIO_UNLINK, path, pri, cb, data);
2449
+ }
2450
+
2451
+ eio_req *eio_rmdir (const char *path, int pri, eio_cb cb, void *data)
2452
+ {
2453
+ return eio__1path (EIO_RMDIR, path, pri, cb, data);
2454
+ }
2455
+
2456
+ eio_req *eio_readdir (const char *path, int flags, int pri, eio_cb cb, void *data)
2457
+ {
2458
+ REQ (EIO_READDIR); PATH; req->int1 = flags; SEND;
2459
+ }
2460
+
2461
+ eio_req *eio_mknod (const char *path, eio_mode_t mode, dev_t dev, int pri, eio_cb cb, void *data)
2462
+ {
2463
+ REQ (EIO_MKNOD); PATH; req->int2 = (long)mode; req->offs = (off_t)dev; SEND;
2464
+ }
2465
+
2466
+ static eio_req *
2467
+ eio__2path (int type, const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2468
+ {
2469
+ REQ (type); PATH;
2470
+
2471
+ req->flags |= EIO_FLAG_PTR2_FREE;
2472
+ req->ptr2 = strdup (new_path);
2473
+ if (!req->ptr2)
2474
+ {
2475
+ eio_api_destroy (req);
2476
+ return 0;
2477
+ }
2478
+
2479
+ SEND;
2480
+ }
2481
+
2482
+ eio_req *eio_link (const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2483
+ {
2484
+ return eio__2path (EIO_LINK, path, new_path, pri, cb, data);
2485
+ }
2486
+
2487
+ eio_req *eio_symlink (const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2488
+ {
2489
+ return eio__2path (EIO_SYMLINK, path, new_path, pri, cb, data);
2490
+ }
2491
+
2492
+ eio_req *eio_rename (const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2493
+ {
2494
+ return eio__2path (EIO_RENAME, path, new_path, pri, cb, data);
2495
+ }
2496
+
2497
+ eio_req *eio_custom (void (*execute)(eio_req *), int pri, eio_cb cb, void *data)
2498
+ {
2499
+ REQ (EIO_CUSTOM); req->feed = execute; SEND;
2500
+ }
2501
+
2502
+ #endif
2503
+
2504
+ eio_req *eio_grp (eio_cb cb, void *data)
2505
+ {
2506
+ const int pri = EIO_PRI_MAX;
2507
+
2508
+ REQ (EIO_GROUP); SEND;
2509
+ }
2510
+
2511
+ #undef REQ
2512
+ #undef PATH
2513
+ #undef SEND
2514
+
2515
+ /*****************************************************************************/
2516
+ /* grp functions */
2517
+
2518
+ void
2519
+ eio_grp_feed (eio_req *grp, void (*feed)(eio_req *req), int limit)
2520
+ {
2521
+ grp->int2 = limit;
2522
+ grp->feed = feed;
2523
+
2524
+ grp_try_feed (grp);
2525
+ }
2526
+
2527
+ void
2528
+ eio_grp_limit (eio_req *grp, int limit)
2529
+ {
2530
+ grp->int2 = limit;
2531
+
2532
+ grp_try_feed (grp);
2533
+ }
2534
+
2535
+ void
2536
+ eio_grp_add (eio_req *grp, eio_req *req)
2537
+ {
2538
+ assert (("cannot add requests to IO::AIO::GRP after the group finished", grp->int1 != 2));
2539
+
2540
+ grp->flags |= EIO_FLAG_GROUPADD;
2541
+
2542
+ ++grp->size;
2543
+ req->grp = grp;
2544
+
2545
+ req->grp_prev = 0;
2546
+ req->grp_next = grp->grp_first;
2547
+
2548
+ if (grp->grp_first)
2549
+ grp->grp_first->grp_prev = req;
2550
+
2551
+ grp->grp_first = req;
2552
+ }
2553
+
2554
+ /*****************************************************************************/
2555
+ /* misc garbage */
2556
+
2557
+ eio_ssize_t
2558
+ eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count)
2559
+ {
2560
+ return eio__sendfile (ofd, ifd, offset, count);
2561
+ }
2562
+