IOWA 1.0.0

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 (502) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTORS +14 -0
  3. data/README.md +23 -0
  4. data/RELEASE_NOTES +77 -0
  5. data/ToDo +21 -0
  6. data/components/CRUDList/CRUDList.html +13 -0
  7. data/components/CRUDList/CRUDList.iwa +136 -0
  8. data/components/Content/Content.html +0 -0
  9. data/components/Content/Content.iwa +143 -0
  10. data/components/Content/example/README +9 -0
  11. data/components/Content/example/cgi/iowa.cgi +10 -0
  12. data/components/Content/example/demo.rb +30 -0
  13. data/components/Content/example/doc/index.html +7 -0
  14. data/components/Content/example/iowa/Content.html +1 -0
  15. data/components/Content/example/iowa/Content.iwa +1 -0
  16. data/components/Content/example/iowa/Main.html +6 -0
  17. data/components/Content/example/iowa/Main.iwa +3 -0
  18. data/components/Content/example/iowa/_content/body +7 -0
  19. data/components/Content/example/iowa/_content/body2 +3 -0
  20. data/components/Content/example/iowa/_content/title +2 -0
  21. data/components/Content/example/iowa/app.cnf +8 -0
  22. data/components/Content/example/iowa/app.rb +8 -0
  23. data/components/Content/example/webrick.rb +38 -0
  24. data/components/Include/Include.html +1 -0
  25. data/components/Include/Include.iwa +30 -0
  26. data/components/Include/readme +5 -0
  27. data/components/JumpTo/JumpTo.html +8 -0
  28. data/components/JumpTo/JumpTo.iwa +8 -0
  29. data/components/JumpTo/readme +6 -0
  30. data/doc/Architecture.txt +6 -0
  31. data/doc/History.txt +33 -0
  32. data/doc/StandardDispatcher.txt +19 -0
  33. data/examples/blog/README +1 -0
  34. data/examples/hello_world/README +17 -0
  35. data/examples/hello_world/htdocs/hello_world_html.html +24 -0
  36. data/examples/hello_world/htdocs/hello_world_ruby.html +41 -0
  37. data/examples/hello_world/iowa/HelloWorld.html +14 -0
  38. data/examples/hello_world/iowa/HelloWorld.iwa +31 -0
  39. data/examples/hello_world/iowa/Index.html +16 -0
  40. data/examples/hello_world/iowa/Index.iwa +5 -0
  41. data/examples/hello_world/iowa/iowa_hello_world.cnf +19 -0
  42. data/examples/hello_world/iowa/iowa_hello_world.rb +5 -0
  43. data/examples/hello_world/iowa/mapfile.cnf +6 -0
  44. data/examples/hw1/iowa/Main.html +1 -0
  45. data/examples/hw1/iowa/README +9 -0
  46. data/examples/hw1/iowa/hw.rb +4 -0
  47. data/examples/hw2/iowa/Main.html +10 -0
  48. data/examples/hw2/iowa/Main.iwa +7 -0
  49. data/examples/hw2/iowa/README +16 -0
  50. data/examples/hw2/iowa/hw.rb +4 -0
  51. data/examples/hw3/iowa/Main.html +11 -0
  52. data/examples/hw3/iowa/Main.iwa +7 -0
  53. data/examples/hw3/iowa/README +22 -0
  54. data/examples/hw3/iowa/hw.rb +4 -0
  55. data/examples/hw4/iowa/Greetings.html +10 -0
  56. data/examples/hw4/iowa/Greetings.iwa +9 -0
  57. data/examples/hw4/iowa/Main.html +12 -0
  58. data/examples/hw4/iowa/Main.iwa +10 -0
  59. data/examples/hw4/iowa/README +28 -0
  60. data/examples/hw4/iowa/hw.rb +4 -0
  61. data/examples/hw5/iowa/Footer.html +2 -0
  62. data/examples/hw5/iowa/Greetings.html +4 -0
  63. data/examples/hw5/iowa/Greetings.iwa +12 -0
  64. data/examples/hw5/iowa/Header.html +6 -0
  65. data/examples/hw5/iowa/Main.html +12 -0
  66. data/examples/hw5/iowa/Main.iwa +13 -0
  67. data/examples/hw5/iowa/README +16 -0
  68. data/examples/hw5/iowa/hw.rb +4 -0
  69. data/examples/template_server/iowa/Content.iwa +121 -0
  70. data/examples/template_server/iowa/Content.view +0 -0
  71. data/examples/template_server/iowa/DBContentDispatcher.rb +112 -0
  72. data/examples/template_server/iowa/DBContentPage.html +3 -0
  73. data/examples/template_server/iowa/DBContentPage.iwa +85 -0
  74. data/examples/template_server/iowa/app.cnf +13 -0
  75. data/examples/template_server/iowa/app.rb +5 -0
  76. data/ext/Classifier/classifier.c +256 -0
  77. data/ext/Classifier/ext_help.h +14 -0
  78. data/ext/Classifier/extconf.rb +5 -0
  79. data/ext/Classifier/tst.h +40 -0
  80. data/ext/Classifier/tst_cleanup.c +24 -0
  81. data/ext/Classifier/tst_delete.c +146 -0
  82. data/ext/Classifier/tst_grow_node_free_list.c +38 -0
  83. data/ext/Classifier/tst_init.c +41 -0
  84. data/ext/Classifier/tst_insert.c +192 -0
  85. data/ext/Classifier/tst_search.c +68 -0
  86. data/ext/http11/README +11 -0
  87. data/ext/http11/ext_help.h +15 -0
  88. data/ext/http11/extconf.rb +5 -0
  89. data/ext/http11/http11.c +534 -0
  90. data/ext/http11/http11.c.dif +422 -0
  91. data/ext/http11/http11_parser.c +1243 -0
  92. data/ext/http11/http11_parser.c.dif +193 -0
  93. data/ext/http11/http11_parser.h +49 -0
  94. data/ext/http11/http11_parser.h.dif +20 -0
  95. data/ext/http11/http11_parser.rl +192 -0
  96. data/ext/httpmachine/Makefile +149 -0
  97. data/ext/httpmachine/extconf.rb +33 -0
  98. data/ext/httpmachine/http.cpp +430 -0
  99. data/ext/httpmachine/http.h +156 -0
  100. data/ext/httpmachine/rubyhttp.cpp +165 -0
  101. data/external/mime-types/LICENCE +18 -0
  102. data/external/mime-types/README +46 -0
  103. data/external/mime-types/doc/classes/MIME.html +120 -0
  104. data/external/mime-types/doc/classes/MIME/InvalidContentType.html +119 -0
  105. data/external/mime-types/doc/classes/MIME/Type.html +866 -0
  106. data/external/mime-types/doc/classes/MIME/Type.src/M000010.html +22 -0
  107. data/external/mime-types/doc/classes/MIME/Type.src/M000011.html +18 -0
  108. data/external/mime-types/doc/classes/MIME/Type.src/M000012.html +19 -0
  109. data/external/mime-types/doc/classes/MIME/Type.src/M000013.html +18 -0
  110. data/external/mime-types/doc/classes/MIME/Type.src/M000014.html +26 -0
  111. data/external/mime-types/doc/classes/MIME/Type.src/M000015.html +33 -0
  112. data/external/mime-types/doc/classes/MIME/Type.src/M000016.html +27 -0
  113. data/external/mime-types/doc/classes/MIME/Type.src/M000017.html +35 -0
  114. data/external/mime-types/doc/classes/MIME/Type.src/M000018.html +34 -0
  115. data/external/mime-types/doc/classes/MIME/Type.src/M000019.html +24 -0
  116. data/external/mime-types/doc/classes/MIME/Type.src/M000020.html +38 -0
  117. data/external/mime-types/doc/classes/MIME/Type.src/M000021.html +22 -0
  118. data/external/mime-types/doc/classes/MIME/Type.src/M000022.html +18 -0
  119. data/external/mime-types/doc/classes/MIME/Type.src/M000023.html +18 -0
  120. data/external/mime-types/doc/classes/MIME/Type.src/M000024.html +18 -0
  121. data/external/mime-types/doc/classes/MIME/Type.src/M000025.html +18 -0
  122. data/external/mime-types/doc/classes/MIME/Type.src/M000026.html +18 -0
  123. data/external/mime-types/doc/classes/MIME/Type.src/M000027.html +18 -0
  124. data/external/mime-types/doc/classes/MIME/Type.src/M000028.html +18 -0
  125. data/external/mime-types/doc/classes/MIME/Type.src/M000029.html +18 -0
  126. data/external/mime-types/doc/classes/MIME/Type.src/M000030.html +19 -0
  127. data/external/mime-types/doc/classes/MIME/Type.src/M000031.html +26 -0
  128. data/external/mime-types/doc/classes/MIME/Types.html +459 -0
  129. data/external/mime-types/doc/classes/MIME/Types.src/M000001.html +19 -0
  130. data/external/mime-types/doc/classes/MIME/Types.src/M000002.html +32 -0
  131. data/external/mime-types/doc/classes/MIME/Types.src/M000003.html +21 -0
  132. data/external/mime-types/doc/classes/MIME/Types.src/M000004.html +18 -0
  133. data/external/mime-types/doc/classes/MIME/Types.src/M000005.html +26 -0
  134. data/external/mime-types/doc/classes/MIME/Types.src/M000006.html +18 -0
  135. data/external/mime-types/doc/classes/MIME/Types.src/M000007.html +18 -0
  136. data/external/mime-types/doc/classes/MIME/Types.src/M000008.html +18 -0
  137. data/external/mime-types/doc/classes/MIME/Types.src/M000009.html +18 -0
  138. data/external/mime-types/doc/created.rid +1 -0
  139. data/external/mime-types/doc/files/ChangeLog.html +320 -0
  140. data/external/mime-types/doc/files/README.html +145 -0
  141. data/external/mime-types/doc/files/lib/mime/types_rb.html +101 -0
  142. data/external/mime-types/doc/fr_class_index.html +30 -0
  143. data/external/mime-types/doc/fr_file_index.html +29 -0
  144. data/external/mime-types/doc/fr_method_index.html +57 -0
  145. data/external/mime-types/doc/index.html +24 -0
  146. data/external/mime-types/doc/rdoc-style.css +208 -0
  147. data/external/mime-types/lib/mime/types.rb +1558 -0
  148. data/external/package.rb +672 -0
  149. data/external/test_support.rb +95 -0
  150. data/external/tmail/README +7 -0
  151. data/external/tmail/tmail.rb +4 -0
  152. data/external/tmail/tmail/address.rb +222 -0
  153. data/external/tmail/tmail/base64.rb +52 -0
  154. data/external/tmail/tmail/compat.rb +39 -0
  155. data/external/tmail/tmail/config.rb +50 -0
  156. data/external/tmail/tmail/encode.rb +447 -0
  157. data/external/tmail/tmail/header.rb +895 -0
  158. data/external/tmail/tmail/info.rb +14 -0
  159. data/external/tmail/tmail/loader.rb +1 -0
  160. data/external/tmail/tmail/mail.rb +869 -0
  161. data/external/tmail/tmail/mailbox.rb +386 -0
  162. data/external/tmail/tmail/mbox.rb +1 -0
  163. data/external/tmail/tmail/net.rb +260 -0
  164. data/external/tmail/tmail/obsolete.rb +123 -0
  165. data/external/tmail/tmail/parser.rb +1475 -0
  166. data/external/tmail/tmail/parser.y +372 -0
  167. data/external/tmail/tmail/port.rb +356 -0
  168. data/external/tmail/tmail/scanner.rb +17 -0
  169. data/external/tmail/tmail/scanner_r.rb +243 -0
  170. data/external/tmail/tmail/stringio.rb +256 -0
  171. data/external/tmail/tmail/textutils.rb +197 -0
  172. data/external/tmail/tmail/tmail.rb +1 -0
  173. data/external/tmail/tmail/utils.rb +23 -0
  174. data/external/win32-process/README +133 -0
  175. data/external/win32-process/lib/win32/process.rb +561 -0
  176. data/external/windows-pr/README +145 -0
  177. data/external/windows-pr/doc/conversion_guide.txt +25 -0
  178. data/external/windows-pr/lib/windows/clipboard.rb +72 -0
  179. data/external/windows-pr/lib/windows/console.rb +323 -0
  180. data/external/windows-pr/lib/windows/device_io.rb +88 -0
  181. data/external/windows-pr/lib/windows/directory.rb +80 -0
  182. data/external/windows-pr/lib/windows/error.rb +313 -0
  183. data/external/windows-pr/lib/windows/eventlog.rb +120 -0
  184. data/external/windows-pr/lib/windows/file.rb +349 -0
  185. data/external/windows-pr/lib/windows/filesystem.rb +16 -0
  186. data/external/windows-pr/lib/windows/handle.rb +31 -0
  187. data/external/windows-pr/lib/windows/library.rb +76 -0
  188. data/external/windows-pr/lib/windows/limits.rb +13 -0
  189. data/external/windows-pr/lib/windows/memory.rb +117 -0
  190. data/external/windows-pr/lib/windows/msvcrt/buffer.rb +48 -0
  191. data/external/windows-pr/lib/windows/msvcrt/file.rb +18 -0
  192. data/external/windows-pr/lib/windows/msvcrt/string.rb +46 -0
  193. data/external/windows-pr/lib/windows/national.rb +557 -0
  194. data/external/windows-pr/lib/windows/path.rb +296 -0
  195. data/external/windows-pr/lib/windows/pipe.rb +77 -0
  196. data/external/windows-pr/lib/windows/process.rb +171 -0
  197. data/external/windows-pr/lib/windows/registry.rb +238 -0
  198. data/external/windows-pr/lib/windows/security.rb +89 -0
  199. data/external/windows-pr/lib/windows/service.rb +183 -0
  200. data/external/windows-pr/lib/windows/shell.rb +88 -0
  201. data/external/windows-pr/lib/windows/sound.rb +52 -0
  202. data/external/windows-pr/lib/windows/synchronize.rb +161 -0
  203. data/external/windows-pr/lib/windows/system_info.rb +70 -0
  204. data/external/windows-pr/lib/windows/unicode.rb +138 -0
  205. data/external/windows-pr/lib/windows/window.rb +22 -0
  206. data/iowa.gemspec +45 -0
  207. data/microprojects/DiskCache/LICENSE +28 -0
  208. data/microprojects/DiskCache/README +17 -0
  209. data/microprojects/DiskCache/external/package.rb +608 -0
  210. data/microprojects/DiskCache/external/test_support.rb +8 -0
  211. data/microprojects/DiskCache/setup.rb +22 -0
  212. data/microprojects/DiskCache/src/iowa/Association.rb +67 -0
  213. data/microprojects/DiskCache/src/iowa/Constants.rb +159 -0
  214. data/microprojects/DiskCache/src/iowa/DiskStore.rb +377 -0
  215. data/microprojects/DiskCache/src/iowa/Hash.rb +63 -0
  216. data/microprojects/DiskCache/src/iowa/Lockfile.rb +575 -0
  217. data/microprojects/DiskCache/src/iowa/Mutex.rb +142 -0
  218. data/microprojects/DiskCache/src/iowa/caches/DiskCache.rb +605 -0
  219. data/microprojects/DiskCache/src/iowa/caches/LRUCache.rb +287 -0
  220. data/microprojects/DiskCache/test/TC_DiskCache.rb +218 -0
  221. data/microprojects/LRUCache/LICENSE +28 -0
  222. data/microprojects/LRUCache/README +13 -0
  223. data/microprojects/LRUCache/external/package.rb +608 -0
  224. data/microprojects/LRUCache/external/test_support.rb +8 -0
  225. data/microprojects/LRUCache/setup.rb +22 -0
  226. data/microprojects/LRUCache/src/iowa/Association.rb +57 -0
  227. data/microprojects/LRUCache/src/iowa/Constants.rb +159 -0
  228. data/microprojects/LRUCache/src/iowa/Hash.rb +63 -0
  229. data/microprojects/LRUCache/src/iowa/Mutex.rb +129 -0
  230. data/microprojects/LRUCache/src/iowa/caches/LRUCache.rb +287 -0
  231. data/microprojects/LRUCache/test/TC_LRUCache.rb +65 -0
  232. data/microprojects/LinkedList/LICENSE +28 -0
  233. data/microprojects/LinkedList/README +13 -0
  234. data/microprojects/LinkedList/external/package.rb +608 -0
  235. data/microprojects/LinkedList/external/test_support.rb +8 -0
  236. data/microprojects/LinkedList/setup.rb +22 -0
  237. data/microprojects/LinkedList/src/iowa/LinkedList.rb +165 -0
  238. data/microprojects/LinkedList/test/TC_LinkedList.rb +42 -0
  239. data/microprojects/README +8 -0
  240. data/setup.rb +116 -0
  241. data/share/iowa/app_skeleton/Main.html +8 -0
  242. data/share/iowa/app_skeleton/Main.iwa +15 -0
  243. data/share/iowa/app_skeleton/app.cnf +48 -0
  244. data/share/iowa/app_skeleton/app.rb +58 -0
  245. data/share/iowa/app_skeleton/models/model.rb +49 -0
  246. data/src/ihc.rb +223 -0
  247. data/src/iowa.cgi +29 -0
  248. data/src/iowa.rb +637 -0
  249. data/src/iowa/AbstractCache.rb +96 -0
  250. data/src/iowa/AcceptLanguage.rb +76 -0
  251. data/src/iowa/Application.rb +928 -0
  252. data/src/iowa/ApplicationStats.rb +72 -0
  253. data/src/iowa/Association.rb +67 -0
  254. data/src/iowa/BindingsParser.rb +62 -0
  255. data/src/iowa/Breakpoint.rb +273 -0
  256. data/src/iowa/CSS.rb +564 -0
  257. data/src/iowa/Client.rb +192 -0
  258. data/src/iowa/Component.rb +405 -0
  259. data/src/iowa/ComponentProxy.rb +26 -0
  260. data/src/iowa/Config.rb +21 -0
  261. data/src/iowa/Constants.rb +226 -0
  262. data/src/iowa/Context.rb +218 -0
  263. data/src/iowa/ContextLogger.rb +16 -0
  264. data/src/iowa/DbPool.rb +222 -0
  265. data/src/iowa/DetachedComponent.rb +18 -0
  266. data/src/iowa/Dispatcher.rb +27 -0
  267. data/src/iowa/DynamicElements.rb +471 -0
  268. data/src/iowa/Element.rb +100 -0
  269. data/src/iowa/Email.rb +287 -0
  270. data/src/iowa/Extensions/AllExtensions.rb +4 -0
  271. data/src/iowa/Extensions/Class.rb +94 -0
  272. data/src/iowa/Extensions/Date.rb +88 -0
  273. data/src/iowa/Extensions/DateTime.rb +88 -0
  274. data/src/iowa/Extensions/Hash.rb +22 -0
  275. data/src/iowa/Extensions/Kernel.rb +6 -0
  276. data/src/iowa/Extensions/Numeric.rb +47 -0
  277. data/src/iowa/Extensions/Object.rb +11 -0
  278. data/src/iowa/Extensions/String.rb +60 -0
  279. data/src/iowa/Extensions/Time.rb +89 -0
  280. data/src/iowa/Extensions/TimeExtensions.rb +6 -0
  281. data/src/iowa/Form.rb +368 -0
  282. data/src/iowa/Hash.rb +85 -0
  283. data/src/iowa/ISAAC.rb +175 -0
  284. data/src/iowa/ImageSize.rb +279 -0
  285. data/src/iowa/IowaComponentMixins.rb +7 -0
  286. data/src/iowa/JSON-lexer.rb +296 -0
  287. data/src/iowa/JSON-objects.rb +201 -0
  288. data/src/iowa/KeyValueCoding.rb +91 -0
  289. data/src/iowa/LinkedList.rb +175 -0
  290. data/src/iowa/Loader.rb +22 -0
  291. data/src/iowa/Lockfile.rb +575 -0
  292. data/src/iowa/Logger.rb +74 -0
  293. data/src/iowa/Monkey.rb +20 -0
  294. data/src/iowa/Mutex.rb +142 -0
  295. data/src/iowa/Policy.rb +70 -0
  296. data/src/iowa/Pool.rb +243 -0
  297. data/src/iowa/PrettyException.rb +1091 -0
  298. data/src/iowa/Request.rb +244 -0
  299. data/src/iowa/Response.rb +133 -0
  300. data/src/iowa/Session.rb +354 -0
  301. data/src/iowa/SessionStats.rb +78 -0
  302. data/src/iowa/String.rb +65 -0
  303. data/src/iowa/Tag.rb +101 -0
  304. data/src/iowa/TemplateParser.rb +236 -0
  305. data/src/iowa/Util.rb +314 -0
  306. data/src/iowa/Webcache.rb +122 -0
  307. data/src/iowa/caches/BiLevelCache.rb +65 -0
  308. data/src/iowa/caches/ClassLimitedCache.rb +67 -0
  309. data/src/iowa/caches/DiskCache.rb +609 -0
  310. data/src/iowa/caches/DiskStore.rb +380 -0
  311. data/src/iowa/caches/LRUCache-alternative.rb +155 -0
  312. data/src/iowa/caches/LRUCache.rb +290 -0
  313. data/src/iowa/caches/SimpleLRUCache.rb +112 -0
  314. data/src/iowa/dispatchers/StandardDispatcher.rb +396 -0
  315. data/src/iowa/dispatchers/StandardDispatcherWithClassifier.rb +93 -0
  316. data/src/iowa/js/iowa_jsonrpc.js +381 -0
  317. data/src/iowa/js/jsonrpc.js +187 -0
  318. data/src/iowa/js/jsonrpc_async.js +261 -0
  319. data/src/iowa/loaders/DiskLoader.rb +50 -0
  320. data/src/iowa/loggers/Analogger.rb +54 -0
  321. data/src/iowa/loggers/AsyncLogger.rb +54 -0
  322. data/src/iowa/loggers/BitBucket.rb +38 -0
  323. data/src/iowa/loggers/Log4R.rb +13 -0
  324. data/src/iowa/loggers/Log4rLogger.rb +48 -0
  325. data/src/iowa/loggers/Logger.rb +29 -0
  326. data/src/iowa/loggers/RubyLogger.rb +9 -0
  327. data/src/iowa/pools/DBConnectionPool.rb +53 -0
  328. data/src/iowa/request/Apache.rb +90 -0
  329. data/src/iowa/request/EMHybrid.rb +59 -0
  330. data/src/iowa/request/ENV.rb +80 -0
  331. data/src/iowa/request/FCGI.rb +68 -0
  332. data/src/iowa/request/HTTPMachine.rb +75 -0
  333. data/src/iowa/request/Mongrel.rb +68 -0
  334. data/src/iowa/request/WEBrick.rb +48 -0
  335. data/src/iowa/version.rb +3 -0
  336. data/src/iowa/webrick/HTTPServer.rb +43 -0
  337. data/src/iowa/webrick/WEBrickServlet.rb +28 -0
  338. data/src/iowa_fcgi_handler.rb +101 -0
  339. data/src/iowa_httpmachine.rb +141 -0
  340. data/src/iowa_hybrid.rb +193 -0
  341. data/src/iowa_hybrid_cluster.rb +231 -0
  342. data/src/iowa_mongrel.rb +136 -0
  343. data/src/iowa_webrick.rb +194 -0
  344. data/src/iowa_webrick_legacy.rb +104 -0
  345. data/src/mod_iowa.rb +104 -0
  346. data/tcss.rb +61 -0
  347. data/test/README.windows +12 -0
  348. data/test/TC_AcceptLanguage.rb +61 -0
  349. data/test/TC_AppConfig.rb +43 -0
  350. data/test/TC_AppConfig/cgi/iowa.cgi +7 -0
  351. data/test/TC_AppConfig/doc/index.html +1 -0
  352. data/test/TC_AppConfig/iowa/Main.html +4 -0
  353. data/test/TC_AppConfig/iowa/Main.iwa +17 -0
  354. data/test/TC_AppConfig/iowa/README +1 -0
  355. data/test/TC_AppConfig/iowa/app.cnf +19 -0
  356. data/test/TC_AppConfig/iowa/app.rb +8 -0
  357. data/test/TC_AppConfig/webrick.rb +38 -0
  358. data/test/TC_Association.rb +29 -0
  359. data/test/TC_BiLevelCache.rb +71 -0
  360. data/test/TC_CGI_Adaptor.rb +55 -0
  361. data/test/TC_CGI_Adaptor/cgi/iowa.cgi +7 -0
  362. data/test/TC_CGI_Adaptor/doc/index.html +1 -0
  363. data/test/TC_CGI_Adaptor/iowa/Main.html +8 -0
  364. data/test/TC_CGI_Adaptor/iowa/Main.iwa +14 -0
  365. data/test/TC_CGI_Adaptor/iowa/README +1 -0
  366. data/test/TC_CGI_Adaptor/iowa/app.cnf +8 -0
  367. data/test/TC_CGI_Adaptor/iowa/app.rb +8 -0
  368. data/test/TC_CGI_Adaptor/webrick.rb +38 -0
  369. data/test/TC_CSS.rb +660 -0
  370. data/test/TC_ClassLimitedCache.rb +89 -0
  371. data/test/TC_Classifier.rb +80 -0
  372. data/test/TC_DbPool.rb +127 -0
  373. data/test/TC_DiskCache.rb +218 -0
  374. data/test/TC_Hybrid.rb +58 -0
  375. data/test/TC_Hybrid/doc/thing.txt +1 -0
  376. data/test/TC_Hybrid/iowa/Main.html +3 -0
  377. data/test/TC_Hybrid/iowa/Main.iwa +7 -0
  378. data/test/TC_Hybrid/iowa/NewPage.html +1 -0
  379. data/test/TC_Hybrid/iowa/NewPage.iwa +5 -0
  380. data/test/TC_Hybrid/iowa/app.cnf +10 -0
  381. data/test/TC_Hybrid/iowa/app.rb +5 -0
  382. data/test/TC_IOWAFunctions/doc/Ajax1.html +1 -0
  383. data/test/TC_IOWAFunctions/doc/Ajax1.iwa +1 -0
  384. data/test/TC_IOWAFunctions/doc/index.html +1 -0
  385. data/test/TC_IOWAFunctions/doc/js/dojo.js +9686 -0
  386. data/test/TC_IOWAFunctions/iowa/Ajax1.html +40 -0
  387. data/test/TC_IOWAFunctions/iowa/Ajax1.iwa +23 -0
  388. data/test/TC_IOWAFunctions/iowa/AjaxWidget.iwa +19 -0
  389. data/test/TC_IOWAFunctions/iowa/AjaxWidget.view +22 -0
  390. data/test/TC_IOWAFunctions/iowa/DanielTest.html +9 -0
  391. data/test/TC_IOWAFunctions/iowa/DanielTest.iwa +10 -0
  392. data/test/TC_IOWAFunctions/iowa/IntervalWidget.html +1 -0
  393. data/test/TC_IOWAFunctions/iowa/IntervalWidget.iwa +14 -0
  394. data/test/TC_IOWAFunctions/iowa/Main.html +1 -0
  395. data/test/TC_IOWAFunctions/iowa/NestedRepeat1.html +12 -0
  396. data/test/TC_IOWAFunctions/iowa/NestedRepeat1.iwa +24 -0
  397. data/test/TC_IOWAFunctions/iowa/RPCResponse.iwa +7 -0
  398. data/test/TC_IOWAFunctions/iowa/RPCResponse.view +1 -0
  399. data/test/TC_IOWAFunctions/iowa/Repeat1.iwa +31 -0
  400. data/test/TC_IOWAFunctions/iowa/Repeat1.view +9 -0
  401. data/test/TC_IOWAFunctions/iowa/Repeat2.iwa +32 -0
  402. data/test/TC_IOWAFunctions/iowa/Repeat2.view +11 -0
  403. data/test/TC_IOWAFunctions/iowa/Repeat3.iwa +44 -0
  404. data/test/TC_IOWAFunctions/iowa/Repeat3.view +18 -0
  405. data/test/TC_IOWAFunctions/iowa/TesCon.html +1 -0
  406. data/test/TC_IOWAFunctions/iowa/TesCon.iwa +5 -0
  407. data/test/TC_IOWAFunctions/iowa/app.cnf +19 -0
  408. data/test/TC_IOWAFunctions/iowa/app.rb +9 -0
  409. data/test/TC_IOWAFunctions/iowa/mapfile.cnf +8 -0
  410. data/test/TC_ISAAC.rb +52 -0
  411. data/test/TC_ImageSize.rb +84 -0
  412. data/test/TC_ImageSize/img.bmp +0 -0
  413. data/test/TC_ImageSize/img.gif +0 -0
  414. data/test/TC_ImageSize/img.jpg +0 -0
  415. data/test/TC_ImageSize/img.pcx +0 -0
  416. data/test/TC_ImageSize/img.pgm +7144 -0
  417. data/test/TC_ImageSize/img.png +0 -0
  418. data/test/TC_ImageSize/img.ppm +0 -0
  419. data/test/TC_ImageSize/img.psd +0 -0
  420. data/test/TC_ImageSize/img.tiff +0 -0
  421. data/test/TC_ImageSize/img.xbm +22 -0
  422. data/test/TC_KeyValueCoding.rb +35 -0
  423. data/test/TC_LRUCache.rb +296 -0
  424. data/test/TC_LinkedList.rb +46 -0
  425. data/test/TC_Lockfile.rb +106 -0
  426. data/test/TC_Minimal.rb +45 -0
  427. data/test/TC_Minimal/app.cnf +8 -0
  428. data/test/TC_Minimal/cgi-bin/iowa.cgi +11 -0
  429. data/test/TC_Minimal/doc/index.html +1 -0
  430. data/test/TC_Minimal/iowa/Main.html +1 -0
  431. data/test/TC_Minimal/iowa/README +1 -0
  432. data/test/TC_Minimal/iowa/app.rb +3 -0
  433. data/test/TC_Minimal/webrick.rb +38 -0
  434. data/test/TC_Mongrel.rb +58 -0
  435. data/test/TC_Mongrel/doc/thing.txt +1 -0
  436. data/test/TC_Mongrel/iowa/Main.html +3 -0
  437. data/test/TC_Mongrel/iowa/Main.iwa +7 -0
  438. data/test/TC_Mongrel/iowa/NewPage.html +1 -0
  439. data/test/TC_Mongrel/iowa/NewPage.iwa +5 -0
  440. data/test/TC_Mongrel/iowa/app.cnf +10 -0
  441. data/test/TC_Mongrel/iowa/app.rb +5 -0
  442. data/test/TC_NoSubclass.rb +56 -0
  443. data/test/TC_NoSubclass/cgi/iowa.cgi +7 -0
  444. data/test/TC_NoSubclass/doc/index.html +1 -0
  445. data/test/TC_NoSubclass/iowa/Main.html +8 -0
  446. data/test/TC_NoSubclass/iowa/Main.iwa +14 -0
  447. data/test/TC_NoSubclass/iowa/README +1 -0
  448. data/test/TC_NoSubclass/iowa/app.cnf +8 -0
  449. data/test/TC_NoSubclass/iowa/app.rb +5 -0
  450. data/test/TC_NoSubclass/webrick.rb +38 -0
  451. data/test/TC_Pool.rb +139 -0
  452. data/test/TC_RenderedCache/doc/thing.txt +1 -0
  453. data/test/TC_RenderedCache/iowa/BigPage.html +1 -0
  454. data/test/TC_RenderedCache/iowa/BigPage.iwa +12 -0
  455. data/test/TC_RenderedCache/iowa/Main.html +3 -0
  456. data/test/TC_RenderedCache/iowa/Main.iwa +7 -0
  457. data/test/TC_RenderedCache/iowa/NewPage.html +1 -0
  458. data/test/TC_RenderedCache/iowa/NewPage.iwa +11 -0
  459. data/test/TC_RenderedCache/iowa/app.cnf +13 -0
  460. data/test/TC_RenderedCache/iowa/app.rb +5 -0
  461. data/test/TC_RenderedCache/iowa/mapfile.map +4 -0
  462. data/test/TC_ResourceURL.rb +73 -0
  463. data/test/TC_ResourceURL/iowa/Main.html +2 -0
  464. data/test/TC_ResourceURL/iowa/Main.iwa +10 -0
  465. data/test/TC_ResourceURL/iowa/app.cnf +10 -0
  466. data/test/TC_ResourceURL/iowa/app.rb +5 -0
  467. data/test/TC_SimpleDetached.rb +41 -0
  468. data/test/TC_StandardDispatcher.rb +362 -0
  469. data/test/TC_StandardDispatcherWithClassifier.rb +358 -0
  470. data/test/TC_String.rb +24 -0
  471. data/test/TC_Tag.rb +41 -0
  472. data/test/TC_Webrick.rb +56 -0
  473. data/test/TC_Webrick/doc/thing.txt +1 -0
  474. data/test/TC_Webrick/iowa/Main.html +3 -0
  475. data/test/TC_Webrick/iowa/Main.iwa +7 -0
  476. data/test/TC_Webrick/iowa/NewPage.html +1 -0
  477. data/test/TC_Webrick/iowa/NewPage.iwa +5 -0
  478. data/test/TC_Webrick/iowa/app.cnf +10 -0
  479. data/test/TC_Webrick/iowa/app.rb +5 -0
  480. data/test/tc_template.rb +15 -0
  481. data/test/tests.conf +19 -0
  482. data/utils/CVS/Entries +3 -0
  483. data/utils/CVS/Repository +1 -0
  484. data/utils/CVS/Root +1 -0
  485. data/utils/QuickCert-1.0.2.tar.gz +0 -0
  486. data/utils/QuickCert-1.0.2/InstalledFiles +7 -0
  487. data/utils/QuickCert-1.0.2/MANIFEST +10 -0
  488. data/utils/QuickCert-1.0.2/Makefile +15 -0
  489. data/utils/QuickCert-1.0.2/README +56 -0
  490. data/utils/QuickCert-1.0.2/bin/QuickCert +355 -0
  491. data/utils/QuickCert-1.0.2/config.save +12 -0
  492. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/README +60 -0
  493. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_c.rb +26 -0
  494. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_s.rb +35 -0
  495. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/qc_config +21 -0
  496. data/utils/QuickCert-1.0.2/lib/QuickCert/defaults.rb +28 -0
  497. data/utils/QuickCert-1.0.2/setup.rb +1312 -0
  498. data/utils/iowa_apps +422 -0
  499. data/utils/smtp_sink.rb +9 -0
  500. data/utils/startup_template.cnf +27 -0
  501. data/utils/startup_template.rb +73 -0
  502. metadata +551 -0
@@ -0,0 +1,91 @@
1
+ require 'iowa/Constants'
2
+
3
+ class Object
4
+
5
+ def takeValueForKey(value, key)
6
+ __send__("#{key}=", value)
7
+ end
8
+
9
+ def valueForKey(key)
10
+ __send__(key)
11
+ end
12
+
13
+ def takeValueForKeyPath(value, keyPath)
14
+ keys = keyPath.split(Iowa::C_dot)
15
+ lastKey = keys.pop
16
+ target = self
17
+ for key in keys
18
+ target = target.valueForKey(key)
19
+ end
20
+ target.takeValueForKey(value, lastKey)
21
+ end
22
+
23
+ def valueForKeyPath(keyPath)
24
+ keys = keyPath.split(Iowa::C_dot)
25
+ result = self
26
+ keys.each_index do |i|
27
+ if keys[i] =~ /^[&](.*)/
28
+ return result.__send__($1) do |val|
29
+ val.valueForKeyPath(keys[i+1..-1].join(Iowa::C_dot))
30
+ end
31
+ end
32
+ result = result.valueForKey keys[i]
33
+ end
34
+ result
35
+ end
36
+
37
+ def valueForKeyPathWithArgs(keyPath,*args)
38
+ keys = keyPath.split(Iowa::C_dot)
39
+ final_method = keys.pop
40
+ result = self
41
+ keys.each_index do |i|
42
+ if keys[i] =~ /^[&](.*)/
43
+ return result.__send__($1) do |val|
44
+ val.valueForKeyPath(keys[i+1..-1].join(Iowa::C_dot))
45
+ end
46
+ end
47
+ result = result.valueForKey keys[i]
48
+ end
49
+ args.length == 0 ? result.__send__(final_method) : result.__send__(final_method,*args)
50
+ end
51
+
52
+ def existsKeyPath?(keyPath)
53
+ keys = keyPath.split(Iowa::C_dot)
54
+ lastKey = keys.pop
55
+ target = self
56
+ keys.each_index do |i|
57
+ if keys[i] =~ /^[&](.*)/
58
+ return target.__send__($1) do |val|
59
+ val.existsKeyPath?(keys[i+1..-1].join(Iowa::C_dot))
60
+ end
61
+ end
62
+ target = target.valueForKey keys[i]
63
+ end
64
+ target.respond_to?(lastKey)
65
+ rescue Exception => e
66
+ false
67
+ end
68
+ end
69
+
70
+ class Hash
71
+
72
+ def takeValueForKey(value, key)
73
+ self[key] = value
74
+ end
75
+
76
+ def valueForKey(key)
77
+ self[key]
78
+ end
79
+ end
80
+
81
+ class Array
82
+
83
+ def takeValueForKey(value, key)
84
+ self[key.to_i] = value
85
+ end
86
+
87
+ def valueForKey(key)
88
+ self[key.to_i]
89
+ end
90
+ end
91
+
@@ -0,0 +1,175 @@
1
+ require 'enumerator'
2
+
3
+ module Iowa
4
+
5
+ # This is a simple linked list implementation with efficient random
6
+ # access of data elements. It was inspired by George Moscovitis'
7
+ # LRUCache implementation found in Facets 1.7.30, but unlike the
8
+ # linked list in that cache, this one does not require the use of a
9
+ # mixin on any class to be stored. The linked list provides the
10
+ # push, pop, shift, unshift, first, last, delete and length methods
11
+ # which work just like their namesakes in the Array class, but it
12
+ # also supports setting and retrieving values by key, just like a
13
+ # hash.
14
+
15
+ class LinkedList
16
+ include Enumerable
17
+
18
+ # Represents a single node of the linked list.
19
+
20
+ class Node
21
+ attr_accessor :key, :value, :prev_node, :next_node
22
+
23
+ def initialize(key=nil,value=nil,prev_node=nil,next_node=nil)
24
+ @key = key
25
+ @value = value
26
+ @prev_node = prev_node
27
+ @next_node = next_node
28
+ end
29
+ end
30
+
31
+ # Create a new LinkedList.
32
+
33
+ def initialize
34
+ @head = Node.new
35
+ @tail = Node.new
36
+ @lookup = Hash.new
37
+ node_join(@head,@tail)
38
+ end
39
+
40
+ # Retrieves the node referenced by the key value provided.
41
+ def [](k)
42
+ @lookup[k].value
43
+ end
44
+
45
+ def []=(k,v)
46
+ if @lookup.has_key?(k)
47
+ @lookup[k].value = v
48
+ else
49
+ n = Node.new(k,v,@head,@head.next_node)
50
+ node_join(n,@head.next_node)
51
+ node_join(@head,n)
52
+ @lookup[k] = n
53
+ end
54
+ v
55
+ end
56
+
57
+ def has_key?(k)
58
+ @lookup.has_key?(k)
59
+ end
60
+ alias :include? :has_key?
61
+
62
+ def empty?
63
+ @lookup.empty?
64
+ end
65
+
66
+ def delete(k)
67
+ n = @lookup.delete(k)
68
+ v = n ? node_purge(n) : nil
69
+ v
70
+ end
71
+
72
+ def first
73
+ @head.next_node.value
74
+ end
75
+
76
+ def last
77
+ @tail.prev_node.value
78
+ end
79
+
80
+ def shift
81
+ k = @head.next_node.key
82
+ n = @lookup.delete(k)
83
+ node_delete(n) if n
84
+ end
85
+
86
+ def unshift(v)
87
+ if @lookup.has_key?(v)
88
+ n = @lookup[v]
89
+ node_delete(n)
90
+ node_join(n,@head.next_node)
91
+ node_join(@head,n)
92
+ else
93
+ n = Node.new(v,v,@head,@head.next_node)
94
+ node_join(n,@head.next_node)
95
+ node_join(@head,n)
96
+ @lookup[v] = n
97
+ end
98
+ v
99
+ end
100
+
101
+ def pop
102
+ k = @tail.prev_node.key
103
+ n = @lookup.delete(k)
104
+ node_delete(n) if n
105
+ end
106
+
107
+ def push(v)
108
+ if @lookup.has_key?(v)
109
+ n = @lookup[v]
110
+ node_delete(n)
111
+ node_join(@tail.prev_node,n)
112
+ node_join(n,@tail)
113
+ else
114
+ n = Node.new(v,v,@tail.prev_node,@tail)
115
+ node_join(@tail.prev_node,n)
116
+ node_join(n,@tail)
117
+ @lookup[v] = n
118
+ end
119
+ v
120
+ end
121
+
122
+ def queue
123
+ r = []
124
+ n = @head
125
+ while (n = n.next_node) and n != @tail
126
+ r << n.key
127
+ end
128
+ r
129
+ end
130
+ alias :keys :queue
131
+
132
+ def to_a
133
+ r = []
134
+ n = @head
135
+ while (n = n.next_node) and n != @tail
136
+ r << n.value
137
+ end
138
+ r
139
+ end
140
+
141
+ def length
142
+ @lookup.length
143
+ end
144
+
145
+ def each
146
+ n = @head
147
+ while (n = n.next_node) and n != @tail
148
+ yield(n.key,n.value)
149
+ end
150
+ end
151
+
152
+ private
153
+
154
+ def node_delete(n)
155
+ node_join(n.prev_node,n.next_node)
156
+ v = n.value
157
+ end
158
+
159
+ def node_purge(n)
160
+ node_join(n.prev_node,n.next_node)
161
+ v = n.value
162
+ n.value = nil
163
+ n.key = nil
164
+ n.next_node = nil
165
+ n.prev_node = nil
166
+ v
167
+ end
168
+
169
+ def node_join(a,b)
170
+ a.next_node = b
171
+ b.prev_node = a
172
+ end
173
+
174
+ end
175
+ end
@@ -0,0 +1,22 @@
1
+ # This is the master loader. It creates instances of each of the loaders
2
+ # that the application will use. The application uses this class to load
3
+ # template data; it does not use the various loaders directly. The logic
4
+ # is to search the Ruby search path for iowa/loaders/* files, and to look
5
+ # in the IOWA paths for /loaders/*. It will require anything that it
6
+ # finds, in the order that they are found. Each loader will register itself
7
+ # with the master loader.
8
+ #
9
+
10
+ module Iowa
11
+
12
+ class Loader
13
+
14
+ LOADERS = []
15
+
16
+ def self.add_loader(loader)
17
+ LOADERS.push loader
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,575 @@
1
+ # The majority of code in this file comes from Ara Howard's lockfile.rb.
2
+ # http://rubyforge.org/project/codeforpeople
3
+ #
4
+ # This version is just trimmed and tweaked a bit differently, and has
5
+ # some code added so that it can use link() based locking, which is
6
+ # fairly portable and NFS safe, but does not work right on systems such
7
+ # as Windows XP, which do not return any sort of inode number to a
8
+ # stat call, or one can use flock() based locking, which works fairly
9
+ # portably, as well, but isn't a good choice for NFS.
10
+ #
11
+ # If the code is not told which method to use, it will conduct a
12
+ # couple tests intended to determine if the link() based locking will
13
+ # work. If it will, that is what it uses. Otherwise, it uses
14
+ # flock() based locking. It remembers the result of the test and
15
+ # automatically uses that as the default for future logfiles.
16
+
17
+ unless defined? $__lockfile__
18
+
19
+ require 'socket'
20
+ require 'timeout'
21
+ require 'fileutils'
22
+ require 'iowa/Constants'
23
+ require 'thread'
24
+
25
+ module Iowa
26
+
27
+ class Lockfile
28
+ class LockError < StandardError; end
29
+ class StolenLockError < LockError; end
30
+ class StackingLockError < LockError; end
31
+ class StatLockError < LockError; end
32
+ class MaxTriesLockError < LockError; end
33
+ class TimeoutLockError < LockError; end
34
+ class NFSLockError < LockError; end
35
+ class UnLockError < LockError; end
36
+
37
+ class SleepCycle < Array
38
+ attr :min
39
+ attr :max
40
+ attr :range
41
+ attr :inc
42
+
43
+ def initialize min, max, inc
44
+ @min, @max, @inc = Float(min), Float(max), Float(inc)
45
+ @range = @max - @min
46
+ raise RangeError, "max(#{ @max }) <= min(#{ @min })" if @max <= @min
47
+ raise RangeError, "inc(#{ @inc }) > range(#{ @range })" if @inc > @range
48
+ raise RangeError, "inc(#{ @inc }) <= 0" if @inc <= 0
49
+ raise RangeError, "range(#{ @range }) <= 0" if @range <= 0
50
+ s = @min
51
+ push(s) and s += @inc while(s <= @max)
52
+ self[-1] = @max if self[-1] < @max
53
+ reset
54
+ end
55
+
56
+ def next
57
+ ret = self[@idx]
58
+ @idx = ((@idx + 1) % self.size)
59
+ ret
60
+ end
61
+
62
+ def reset
63
+ @idx = 0
64
+ end
65
+ end
66
+
67
+ HOSTNAME = Socket::gethostname
68
+
69
+ UNKNOWN = Iowa::UnknownValue.instance
70
+ DEFAULT_RETRIES = nil # maximum number of attempts
71
+ DEFAULT_TIMEOUT = 30 # the longest we will try
72
+ DEFAULT_MAX_AGE = 1024 # lockfiles older than this are stale
73
+ DEFAULT_SLEEP_INC = 2 # sleep cycle is this much longer each time
74
+ DEFAULT_MIN_SLEEP = 2 # shortest sleep time
75
+ DEFAULT_MAX_SLEEP = 10 # longest sleep time
76
+ DEFAULT_SUSPEND = 15 # iff we steal a lock wait this long before we go on
77
+ DEFAULT_REFRESH = 8 # how often we touch/validate the lock
78
+ DEFAULT_DONT_CLEAN = false # iff we leave lock files lying around
79
+ DEFAULT_POLL_RETRIES = 16 # this many polls makes one 'try'
80
+ DEFAULT_POLL_MAX_SLEEP = 0.08 # the longest we'll sleep between polls
81
+ DEFAULT_DONT_SWEEP = false # if we cleanup after other process on our host
82
+ DEFAULT_DONT_USE_LOCK_ID = false # if we dump lock info into lockfile
83
+ DEFAULT_USE_FLOCK = Iowa::UnknownValue.instance # by default, try to figure it out
84
+
85
+
86
+ class << self
87
+ attr :retries, true
88
+ attr :max_age, true
89
+ attr :sleep_inc, true
90
+ attr :min_sleep, true
91
+ attr :max_sleep, true
92
+ attr :suspend, true
93
+ attr :timeout, true
94
+ attr :refresh, true
95
+ attr :dont_clean, true
96
+ attr :poll_retries, true
97
+ attr :poll_max_sleep, true
98
+ attr :dont_sweep, true
99
+ attr :dont_use_lock_id, true
100
+ attr :use_flock, true
101
+
102
+ def init
103
+ @retries = DEFAULT_RETRIES
104
+ @max_age = DEFAULT_MAX_AGE
105
+ @sleep_inc = DEFAULT_SLEEP_INC
106
+ @min_sleep = DEFAULT_MIN_SLEEP
107
+ @max_sleep = DEFAULT_MAX_SLEEP
108
+ @suspend = DEFAULT_SUSPEND
109
+ @timeout = DEFAULT_TIMEOUT
110
+ @refresh = DEFAULT_REFRESH
111
+ @dont_clean = DEFAULT_DONT_CLEAN
112
+ @poll_retries = DEFAULT_POLL_RETRIES
113
+ @poll_max_sleep = DEFAULT_POLL_MAX_SLEEP
114
+ @dont_sweep = DEFAULT_DONT_SWEEP
115
+ @dont_use_lock_id = DEFAULT_DONT_USE_LOCK_ID
116
+ @use_flock = DEFAULT_USE_FLOCK
117
+ end
118
+ end
119
+
120
+ self.init
121
+
122
+ attr :klass
123
+ attr :path
124
+ attr :opts
125
+ attr :locked
126
+ attr :thief
127
+ attr :dirname
128
+ attr :basename
129
+ attr :clean
130
+ attr :retries
131
+ attr :max_age
132
+ attr :sleep_inc
133
+ attr :min_sleep
134
+ attr :max_sleep
135
+ attr :suspend
136
+ attr :refresh
137
+ attr :timeout
138
+ attr :dont_clean
139
+ attr :poll_retries
140
+ attr :poll_max_sleep
141
+ attr :dont_sweep
142
+ attr :dont_use_lock_id
143
+ attr :use_flock
144
+
145
+ alias thief? thief
146
+ alias locked? locked
147
+
148
+ def self::create(path, *a, &b)
149
+ opts = {
150
+ 'retries' => 0,
151
+ 'min_sleep' => 0,
152
+ 'max_sleep' => 1,
153
+ 'sleep_inc' => 1,
154
+ 'max_age' => nil,
155
+ 'suspend' => 0,
156
+ 'refresh' => nil,
157
+ 'timeout' => nil,
158
+ 'poll_retries' => 0,
159
+ 'dont_clean' => true,
160
+ 'dont_sweep' => false,
161
+ 'dont_use_lock_id' => true,
162
+ 'use_flock' => false
163
+ }
164
+ begin
165
+ new(path, opts).lock
166
+ rescue LockError
167
+ raise Errno::EEXIST, path
168
+ end
169
+ open(path, *a, &b)
170
+ end
171
+
172
+ def initialize(path, opts = {}, &block)
173
+ @klass = self.class
174
+ @path = path
175
+ @opts = opts
176
+
177
+ @retries = getopt('retries') || @klass.retries
178
+ @max_age = getopt('max_age') || @klass.max_age
179
+ @sleep_inc = getopt('sleep_inc') || @klass.sleep_inc
180
+ @min_sleep = getopt('min_sleep') || @klass.min_sleep
181
+ @max_sleep = getopt('max_sleep') || @klass.max_sleep
182
+ @suspend = getopt('suspend') || @klass.suspend
183
+ @timeout = getopt('timeout') || @klass.timeout
184
+ @refresh = getopt('refresh') || @klass.refresh
185
+ @dont_clean = getopt('dont_clean') || @klass.dont_clean
186
+ @poll_retries = getopt('poll_retries') || @klass.poll_retries
187
+ @poll_max_sleep = getopt('poll_max_sleep') || @klass.poll_max_sleep
188
+ @dont_sweep = getopt('dont_sweep') || @klass.dont_sweep
189
+ @dont_use_lock_id = getopt('dont_use_lock_id') || @klass.dont_use_lock_id
190
+ @use_flock = getopt('use_flock') || @klass.use_flock
191
+
192
+ @sleep_cycle = SleepCycle::new @min_sleep, @max_sleep, @sleep_inc
193
+
194
+ @clean = @dont_clean ? nil : lambda{ File::unlink @path rescue nil }
195
+ @dirname = File::dirname @path
196
+ @basename = File::basename @path
197
+ @thief = false
198
+ @locked = false
199
+ @mutex = Mutex.new
200
+
201
+ lock(&block) if block
202
+ end
203
+
204
+ def lock
205
+ @mutex.synchronize do
206
+ if @use_flock == UNKNOWN
207
+ # Test to see if we should use flock by first stating a known file,
208
+ # and checking to see if an inode value is returned, and then by
209
+ # trying to create a test link in the lockfile path and seeing if
210
+ # that works. If either fails, use flock.
211
+ begin
212
+ known_stat = File::stat(__FILE__)
213
+ @use_flock = (known_stat.ino.to_i == 0)
214
+ rescue
215
+ @use_flock = true
216
+ end
217
+
218
+ unless @use_flock == true
219
+ begin
220
+ orig_file = tmpnam(@path,'orig_file')
221
+ link_file = tmpnam(@path,'link_file')
222
+ File.open(orig_file,'w+') {}
223
+ File::link(orig_file,link_file)
224
+ File::unlink orig_file
225
+ File::unlink link_file
226
+ @use_flock = false
227
+ rescue
228
+ @use_flock = true
229
+ end
230
+ end
231
+
232
+ self.class.use_flock = @use_flock
233
+ end
234
+
235
+ ret = nil
236
+
237
+ if @use_flock == true
238
+ begin
239
+ Timeout::timeout(@timeout) do
240
+ if block_given?
241
+ File.open(@path,'w+') do |fh|
242
+ fh.flock(File::LOCK_EX)
243
+ @locked = true
244
+ ret = yield @path
245
+ fh.flock(File::LOCK_UN)
246
+ @locked = false
247
+ end
248
+ return ret
249
+ else
250
+ @flock_fh = File.open(@path,'w+')
251
+ @flock_fh.flock(File::LOCK_EX)
252
+ @locked = true
253
+ return self
254
+ end
255
+ end
256
+ rescue
257
+ File::unlink @path if FileText.exist? @path
258
+ end
259
+ else
260
+ sweep unless @dont_sweep
261
+
262
+ attempt do
263
+ begin
264
+ @sleep_cycle.reset
265
+ create_tmplock do |f|
266
+ begin
267
+ Timeout::timeout(@timeout) do
268
+ tmp_path = f.path
269
+ tmp_stat = f.lstat
270
+ n_retries = 0
271
+ begin
272
+ i = 0
273
+ begin
274
+ begin
275
+ File::link tmp_path, @path
276
+ rescue Errno::ENOENT
277
+ try_again!
278
+ end
279
+ lock_stat = File::lstat @path
280
+ raise StatLockError, "stat's do not agree" unless
281
+ tmp_stat.rdev == lock_stat.rdev and tmp_stat.ino == lock_stat.ino
282
+ @locked = true
283
+ rescue => e
284
+ i += 1
285
+ unless i >= @poll_retries
286
+ t = [rand(@poll_max_sleep), @poll_max_sleep].min
287
+ sleep t
288
+ retry
289
+ end
290
+ raise
291
+ end
292
+
293
+ rescue => e
294
+ n_retries += 1
295
+ case validlock?
296
+ when true
297
+ raise MaxTriesLockError, "surpased retries <#{ @retries }>" if
298
+ @retries and n_retries >= @retries
299
+ sleeptime = @sleep_cycle.next
300
+ sleep sleeptime
301
+ when false
302
+ begin
303
+ File::unlink @path
304
+ @thief = true
305
+ warn "<#{ @path }> stolen by <#{ Process.pid }> at <#{ timestamp }>"
306
+ rescue Errno::ENOENT
307
+ end
308
+ sleep @suspend
309
+ when nil
310
+ raise MaxTriesLockError, "surpased retries <#{ @retries }>" if
311
+ @retries and n_retries >= @retries
312
+ end
313
+ retry
314
+ end # begin
315
+ end # timeout
316
+ rescue Timeout::Error
317
+ raise TimeoutLockError, "surpassed timeout <#{ @timeout }>"
318
+ end # begin
319
+ end # create_tmplock
320
+
321
+ if block_given?
322
+ stolen = false
323
+ refresher = (@refresh ? new_refresher : nil)
324
+ begin
325
+ begin
326
+ ret = yield @path
327
+ rescue StolenLockError
328
+ stolen = true
329
+ raise
330
+ end
331
+ ensure
332
+ begin
333
+ refresher.kill if refresher and refresher.status
334
+ ensure
335
+ unlock unless stolen
336
+ end
337
+ end
338
+ else
339
+ ObjectSpace.define_finalizer self, @clean if @clean
340
+ ret = self
341
+ end
342
+ rescue Errno::ESTALE, Errno::EIO => e
343
+ raise(NFSLockError, errmsg(e))
344
+ end
345
+ end
346
+
347
+ return ret
348
+ end
349
+ end
350
+ end
351
+
352
+ def sweep
353
+ begin
354
+ glob = File::join(@dirname, ".*lck")
355
+ paths = Dir[glob]
356
+ paths.each do |path|
357
+ begin
358
+ basename = File::basename path
359
+ pat = %r/^\s*\.([^_]+)_([^_]+)/o
360
+ if pat.match(basename)
361
+ host, pid = $1, $2
362
+ else
363
+ next
364
+ end
365
+ host.gsub!(%r/^\.+|\.+$/,'')
366
+ quad = host.split %r/\./
367
+ host = quad.first
368
+ pat = %r/^\s*#{ host }/i
369
+ if pat.match(HOSTNAME) and %r/^\s*\d+\s*$/.match(pid)
370
+ unless alive?(pid)
371
+ FileUtils::rm_f path
372
+ else
373
+ end
374
+ else
375
+ end
376
+ rescue
377
+ next
378
+ end
379
+ end
380
+ rescue => e
381
+ warn(errmsg(e))
382
+ end
383
+ end
384
+
385
+ def alive? pid
386
+ pid = Integer("#{ pid }")
387
+ begin
388
+ Process::kill 0, pid
389
+ true
390
+ rescue Errno::ESRCH
391
+ false
392
+ end
393
+ end
394
+
395
+ def unlock
396
+ raise UnLockError, "<#{ @path }> is not locked!" unless @locked
397
+ if @flock_fh
398
+ begin
399
+ @flock_fh.flock(File::LOCK_UN)
400
+ @flock_fh.close
401
+ File::unlink @path
402
+ rescue Errno::ENOENT
403
+ raise StolenLockError, @path
404
+ end
405
+ else
406
+ begin
407
+ File::unlink @path
408
+ rescue Errno::ENOENT
409
+ raise StolenLockError, @path
410
+ ensure
411
+ @thief = false
412
+ @locked = false
413
+ ObjectSpace.undefine_finalizer self if @clean
414
+ end
415
+ end
416
+ end
417
+
418
+ def new_refresher
419
+ Thread::new(Thread::current, @path, @refresh, @dont_use_lock_id) do |thread, path, refresh, dont_use_lock_id|
420
+ loop do
421
+ begin
422
+ touch path
423
+ unless dont_use_lock_id
424
+ loaded = load_lock_id(IO.read(path))
425
+ raise unless loaded == @lock_id
426
+ end
427
+ sleep refresh
428
+ rescue Exception => e
429
+ thread.raise StolenLockError
430
+ Thread::exit
431
+ end
432
+ end
433
+ end
434
+ end
435
+
436
+ def validlock?
437
+ if @max_age
438
+ uncache @path rescue nil
439
+ begin
440
+ return((Time.now - File::stat(@path).mtime) < @max_age)
441
+ rescue Errno::ENOENT
442
+ return nil
443
+ end
444
+ else
445
+ exist = File::exist?(@path)
446
+ return(exist ? true : nil)
447
+ end
448
+ end
449
+
450
+ def uncache file
451
+ refresh = nil
452
+ begin
453
+ is_a_file = File === file
454
+ path = (is_a_file ? file.path : file.to_s)
455
+ stat = (is_a_file ? file.stat : File::stat(file.to_s))
456
+ refresh = tmpnam(File::dirname(path))
457
+ File::link path, refresh
458
+ File::chmod stat.mode, path
459
+ File::utime stat.atime, stat.mtime, path
460
+ ensure
461
+ begin
462
+ File::unlink refresh if refresh
463
+ rescue Errno::ENOENT
464
+ end
465
+ end
466
+ end
467
+
468
+ def create_tmplock
469
+ tmplock = tmpnam @dirname
470
+ begin
471
+ create(tmplock) do |f|
472
+ unless dont_use_lock_id
473
+ @lock_id = gen_lock_id
474
+ dumped = dump_lock_id
475
+ f.write dumped
476
+ f.flush
477
+ end
478
+ yield f
479
+ end
480
+ ensure
481
+ begin; File::unlink tmplock; rescue Errno::ENOENT; end if tmplock
482
+ end
483
+ end
484
+
485
+ def gen_lock_id
486
+ Hash[
487
+ 'host' => "#{ HOSTNAME }",
488
+ 'pid' => "#{ Process.pid }",
489
+ 'ppid' => "#{ Process.ppid }",
490
+ 'time' => timestamp,
491
+ ]
492
+ end
493
+
494
+ def timestamp
495
+ time = Time.now
496
+ usec = time.usec.to_s
497
+ usec << '0' while usec.size < 6
498
+ "#{ time.strftime('%Y-%m-%d %H:%M:%S') }.#{ usec }"
499
+ end
500
+
501
+ def dump_lock_id lock_id = @lock_id
502
+ "host: %s\npid: %s\nppid: %s\ntime: %s\n" %
503
+ lock_id.values_at('host','pid','ppid','time')
504
+ end
505
+
506
+ def load_lock_id buf
507
+ lock_id = {}
508
+ kv = %r/([^:]+):(.*)/o
509
+ buf.each do |line|
510
+ m = kv.match line
511
+ k, v = m[1], m[2]
512
+ next unless m and k and v
513
+ lock_id[k.strip] = v.strip
514
+ end
515
+ lock_id
516
+ end
517
+
518
+ def tmpnam dir, seed = File::basename($0)
519
+ pid = Process.pid
520
+ time = Time.now
521
+ sec = time.to_i
522
+ usec = time.usec
523
+ "%s%s.%s_%d_%s_%d_%d_%d.lck" %
524
+ [dir, File::SEPARATOR, HOSTNAME, pid, seed, sec, usec, rand(sec)]
525
+ end
526
+
527
+ def create path
528
+ umask = nil
529
+ f = nil
530
+ begin
531
+ umask = File::umask 022
532
+ f = open path, File::WRONLY|File::CREAT|File::EXCL, 0644
533
+ ensure
534
+ File::umask umask if umask
535
+ end
536
+ return(block_given? ? begin; yield f; ensure; f.close; end : f)
537
+ end
538
+
539
+ def touch path
540
+ FileUtils.touch path
541
+ end
542
+
543
+ def getopt key
544
+ @opts[key] || @opts[key.to_s] || @opts[key.to_s.intern]
545
+ end
546
+
547
+ def to_str
548
+ @path
549
+ end
550
+ alias to_s to_str
551
+
552
+ def errmsg e
553
+ "%s (%s)\n%s\n" % [e.class, e.message, e.backtrace.join("\n")]
554
+ end
555
+
556
+ def attempt
557
+ ret = nil
558
+ loop{ break unless catch('attempt'){ ret = yield } == 'try_again' }
559
+ ret
560
+ end
561
+
562
+ def try_again!
563
+ throw 'attempt', 'try_again'
564
+ end
565
+ alias again! try_again!
566
+
567
+ def give_up!
568
+ throw 'attempt', 'give_up'
569
+ end
570
+ end
571
+
572
+ end
573
+
574
+ $__lockfile__ == __FILE__
575
+ end