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,67 @@
1
+ require 'iowa/caches/LRUCache'
2
+ require 'iowa/LinkedList'
3
+
4
+ module Iowa
5
+ module Caches
6
+
7
+ # Variation on the LRUCache that lets a class limit the number of instances
8
+ # of itself that can be stored in the cache.
9
+
10
+ class ClassLimitedCache < Iowa::Caches::LRUCache
11
+
12
+ def initialize(args)
13
+ super(args)
14
+ @class_lookup = {}
15
+ end
16
+
17
+ def class_node_prune(val_class)
18
+ if val_class.respond_to?(:max_cache_entries)
19
+ unless @class_lookup.has_key?(val_class)
20
+ @class_lookup[val_class] = Iowa::LinkedList.new
21
+ end
22
+ if @class_lookup[val_class].length >= val_class.max_cache_entries
23
+ k = @class_lookup[val_class].pop
24
+ node_purge(@lookup[k])
25
+ end
26
+ end
27
+ end
28
+
29
+ def []=(k,v)
30
+ @mutex.lock
31
+ class_node_prune(v.class)
32
+ @class_lookup[v.class][k] = k if @class_lookup.has_key?(v.class)
33
+ super
34
+ @mutex.unlock
35
+ end
36
+
37
+ def push(v)
38
+ @mutex.lock
39
+ class_node_prune(v.class)
40
+ @class_lookup[v.class].push v if @class_lookup.has_key?(v.class)
41
+ @mutex.unlock
42
+ end
43
+
44
+ def unshift(v)
45
+ @mutex.lock
46
+ class_node_prune(v.class)
47
+ @class_lookup[v.class].unshift v if @class_lookup.has_key?(v.class)
48
+ @mutex.unlock
49
+ end
50
+
51
+ def include_class?(klass)
52
+ @class_lookup.has_key? klass
53
+ end
54
+
55
+ def queue_for_class(klass)
56
+ @class_lookup[klass].queue
57
+ end
58
+
59
+ def node_purge(n)
60
+ vc = n.value.class
61
+ @class_lookup[vc].delete(n.key) if @class_lookup.has_key?(vc)
62
+ super
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,609 @@
1
+ require 'thread'
2
+ require 'iowa/AbstractCache'
3
+ require 'iowa/Lockfile'
4
+ require 'digest/sha2'
5
+ require 'digest/rmd160'
6
+ require 'fileutils'
7
+ require 'find'
8
+ require 'tmpdir'
9
+ require 'iowa/caches/LRUCache'
10
+
11
+ class Mutex
12
+ def synchronize_unless(cnd)
13
+ unless cnd
14
+ synchronize {yield}
15
+ else
16
+ yield
17
+ end
18
+ end
19
+ end
20
+
21
+ module Iowa
22
+
23
+ module Caches
24
+
25
+ # DiskCache is an LRU cache, but it's data store is not a RAM store.
26
+ # Rather, it serializes its objects to disk. Generally, if an item
27
+ # is found in an DiskCache, it should be freshened into an in-RAM
28
+ # cache and deleted from the DiskCache.
29
+ #
30
+ # The intent of this cache is that it can, with flat RAM usage,
31
+ # cache, indefinitely, an arbitrary number of elements.
32
+ # So, there needs to be a fast way of representing the cache and
33
+ # and queue to disk. The TTL cache from the standard LRUCache
34
+ # is not needed because the filesystem will provide that information.
35
+ # The filesystem will also be used to preserve the other data, as well.
36
+ #
37
+ # The system will implement the cache as an on-disk linked list.
38
+ # By storing the elements in disk buckets based on a very simple
39
+ # hasing of the keys, we'll avoid storing all files into the same
40
+ # directory, and by storing files according to a hashing of the key,
41
+ # we allow efficient lookup of a cache entry. Each entry will have
42
+ # a data file accompanying it that will encode the key of the
43
+ # element ahead of it and behind it in the cache. There will also
44
+ # be a special data file that will encode the first and last
45
+ # elements in the list.
46
+ # This will permit rapid access to an individual element, and
47
+ # manipulation of the list without keeping in RAM any permanent
48
+ # state information on the list.
49
+ #
50
+ # Locking can be done with just a mutex, or if used in a
51
+ # multiprocess capacity, locking can be done with a lockfile from
52
+ # Iowa::Lockfile.
53
+
54
+ class DiskCache < Iowa::AbstractCache
55
+
56
+ DEFAULT_BUCKET_WIDTH = 2
57
+ DEFAULT_BUCKET_DEPTH = 2
58
+
59
+ class NoCacheDir < Exception
60
+ def initialize(*args)
61
+ @bad_dir = args[0]
62
+ end
63
+
64
+ def to_s
65
+ "The cache directory (#{@bad_dir}) does not exist."
66
+ end
67
+ end
68
+
69
+ class DirNotEmpty < Exception
70
+ def initialize(*args)
71
+ @bad_dir = args[0]
72
+ end
73
+
74
+ def to_s
75
+ "The cache directory (#{@bad_dir}) is not empty."
76
+ end
77
+ end
78
+
79
+ class DeletedValue
80
+ attr_accessor :val
81
+ def initialize(v)
82
+ @val = v
83
+ end
84
+ end
85
+
86
+ def initialize(arg1, force = nil, width = DEFAULT_BUCKET_WIDTH, depth = DEFAULT_BUCKET_DEPTH, use_lockfile = false)
87
+ @transaction_cache = []
88
+ @transaction_lock = [nil,Mutex.new]
89
+ @cache_dir = nil
90
+ if arg1.respond_to?(:keys)
91
+ oargs = arg1
92
+ arg1 = Iowa::Hash.new
93
+ arg1.step_merge!(oargs)
94
+ arg1.stringify_keys!
95
+ if arg1[Cdirectory]
96
+ @cache_dir = arg1[Cdirectory]
97
+ else
98
+ @cache_dir = File.join(Dir::tmpdir,"tmp#{Time.now.to_f}")
99
+ FileUtils.mkdir(@cache_dir)
100
+ end
101
+ set_cachefile_paths
102
+ force = arg1[Cforce] || force
103
+ arg1[Cmaxsize] ||= getdata(@cache_maxsize) if FileTest.exist?(@cache_maxsize)
104
+ arg1[Cttl] ||= getdata(@cache_maxttl) if FileTest.exist?(@cache_maxttl)
105
+ arg1[Cmaxsize] ||= 1000
106
+ @bucket_depth = arg1[Cdepth] || depth
107
+ @bucket_width = arg1[Cwidth] || width
108
+ @use_lockfile = arg1[Cuse_lockfile] || use_lockfile
109
+ else
110
+ @cache_dir = arg1
111
+ set_cachefile_paths
112
+ arg1 = {}
113
+ arg1[Cmaxsize] = getdata(@cache_maxsize) if FileTest.exist?(@cache_maxsize)
114
+ arg1[Cttl] = getdata(@cache_maxttl) if FileTest.exist?(@cache_maxttl)
115
+ @bucket_depth = depth
116
+ @bucket_width = width
117
+ @use_lockfile = use_lockfile
118
+ end
119
+
120
+ super(arg1)
121
+
122
+ @bucket_depth_array = (0..(@bucket_depth - 1)).to_a
123
+ @locked = false
124
+
125
+ unless @use_lockfile
126
+ @mutex = Mutex.new
127
+ else
128
+ @lockfile = Iowa::Lockfile.new(File::join(@cache_dir,'cachelock.lck'))
129
+ end
130
+
131
+ if !FileTest.exist?(@cache_dir)
132
+ if force
133
+ # Force creation of the directory.
134
+ FileUtils.mkdir_p(@cache_dir)
135
+ else
136
+ # Dir doesn't exist, and we aren't forcing, so throw exception.
137
+ raise Iowa::Caches::DiskCache::NoCacheDir.new(@cache_dir)
138
+ end
139
+ end
140
+
141
+ # Check to see if directory is empty.
142
+ # If empty, create head and tail files.
143
+ # If not empty, and lacks head and tail files, and create new, empty
144
+ # head and tail files if force is set, or throw exception if unset.
145
+ # If it has head and tail files, cheer and move on.
146
+
147
+ lock_cache do
148
+ if Dir[File.join(@cache_dir,'*')].length == 0
149
+ create_head_and_tail_files
150
+ else
151
+ if !(FileTest.exist?(@cache_head) and FileTest.exist?(@cache_tail))
152
+ if force
153
+ create_head_and_tail_files
154
+ else
155
+ raise Iowa::Caches::DiskCache::DirNotEmpty
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ # Yay. There is an existing cache!
162
+
163
+ putdata(@max,@cache_maxsize)
164
+ putdata(@maxttl,@cache_maxttl)
165
+ end
166
+
167
+ # Check to see if the cache contains the given key.
168
+
169
+ def include?(key)
170
+ if !@bypass_transactions and transaction_cache_include?(key)
171
+ if transaction_cache_get(key).is_a?(DeletedValue)
172
+ false
173
+ else
174
+ true
175
+ end
176
+ else
177
+ FileTest.exist?(datafile_for_key(key))
178
+ end
179
+ end
180
+
181
+ # Remove a key/value pair from the cache, by key.
182
+
183
+ def delete(key)
184
+ lock_cache do
185
+ if !@bypass_transactions and transaction_cache_include?(key)
186
+ tcg = transaction_cache_get(key)
187
+ unless tcg.is_a?(DeletedValue)
188
+ @transaction_cache.last[key] = DeletedValue.new(tcg)
189
+ end
190
+ elsif FileTest.exist?(datafile_for_key(key))
191
+ if @transaction_lock[0] and @transaction_cache.length > 0
192
+ @transaction_cache.last[key] = DeletedValue.new(self[key])
193
+ else
194
+ # Open the inf file and find this elements head and tail.
195
+
196
+ links = getdata(linkfile_for_key(key),false)
197
+
198
+ # Delete the dat file and the inf file.
199
+
200
+ File::unlink(linkfile_for_key(key))
201
+ File::unlink(datafile_for_key(key))
202
+ File::unlink(keyfile_for_key(key))
203
+
204
+ # Open the inf file for the head and tail and point them
205
+ # at eachother.
206
+
207
+ if links[:head]
208
+ headlink_file = File.join(path_for_hash(links[:head]),"#{links[:head]}.inf")
209
+ headlinks = getdata(headlink_file,false)
210
+ headlinks[:tail] = links[:tail]
211
+ putdata(headlinks,headlink_file)
212
+ else
213
+
214
+ # This element is the head of the list. So, it's tail is the new head.
215
+
216
+ putdata(links[:tail],@cache_head)
217
+ end
218
+
219
+ if links[:tail]
220
+ taillink_file = File.join(path_for_hash(links[:tail]),"#{links[:tail]}.inf")
221
+ taillinks = getdata(taillink_file,false)
222
+ taillinks[:head] = links[:head]
223
+ putdata(taillinks,taillink_file)
224
+ else
225
+
226
+ # This element is the tail of the list. So, it's head is the new tail.
227
+
228
+ putdata(links[:head],@cache_tail)
229
+ end
230
+
231
+ # Finally, reduce the cache counter.
232
+
233
+ new_count = getdata(@cache_count,false) - 1
234
+ putdata(new_count,@cache_count)
235
+ end
236
+ end
237
+ end
238
+ end
239
+
240
+ # Return the element identified by the given key.
241
+
242
+ def [](key)
243
+ r = nil
244
+ lock_cache do
245
+ if !@bypass_transactions and transaction_cache_include?(key)
246
+ transaction_cache_get(key)
247
+ else
248
+ datafile = datafile_for_key(key)
249
+ if FileTest.exist?(datafile)
250
+ #r = getdata(datafile)
251
+ FileUtils::touch(datafile)
252
+ links = getdata(linkfile_for_key(key),false)
253
+
254
+ if links[:head]
255
+ headlink_file = File.join(path_for_hash(links[:head]),"#{links[:head]}.inf")
256
+ headlinks = getdata(headlink_file,false)
257
+ headlinks[:tail] = links[:tail]
258
+ putdata(headlinks,headlink_file)
259
+ else
260
+ putdata(links[:tail],@cache_head)
261
+ end
262
+
263
+ if links[:tail]
264
+ taillink_file = File.join(path_for_hash(links[:tail]),"#{links[:tail]}.inf")
265
+ taillinks = getdata(taillink_file,false)
266
+ taillinks[:head] = links[:head]
267
+ putdata(taillinks,taillink_file)
268
+ else
269
+ putdata(links[:head],@cache_tail)
270
+ end
271
+
272
+ current_head = getdata(@cache_head,false)
273
+ current_key_hash = hash_for_key(key)
274
+ unless current_key_hash == current_head
275
+ current_tail = getdata(@cache_tail,false)
276
+ putdata({:head => nil, :tail => current_head},linkfile_for_key(key))
277
+ putdata(current_key_hash,@cache_head)
278
+ putdata(current_key_hash,@cache_tail) unless current_tail
279
+ if current_head
280
+ taillink_file = File.join(path_for_hash(current_head),"#{current_head}.inf")
281
+ taillinks = getdata(taillink_file,false)
282
+ taillinks[:head] = current_key_hash
283
+ putdata(taillinks,taillink_file)
284
+ end
285
+ end
286
+ r = getdata(datafile,false)
287
+ end
288
+ end
289
+ end
290
+ r
291
+ end
292
+
293
+ def prune
294
+ tail = getdata(@cache_tail)
295
+ delete(getdata(File.join(path_for_hash(tail),"#{tail}.key"))) if tail
296
+ end
297
+
298
+ def attach(key, val)
299
+ # Values are always attached at the head of the list.
300
+ lock_cache do
301
+ already_in_cache = include?(key)
302
+
303
+ putdata((getdata(@cache_count) + 1),@cache_count,false) unless already_in_cache
304
+ # Write the data file.
305
+ putdata(val,datafile_for_key(key))
306
+ # Write the key file.
307
+ putdata(key,keyfile_for_key(key)) unless already_in_cache
308
+
309
+ if already_in_cache
310
+ links = getdata(linkfile_for_key(key),false)
311
+
312
+ if links[:head]
313
+ headlink_file = File.join(path_for_hash(links[:head]),"#{links[:head]}.inf")
314
+ headlinks = getdata(headlink_file,false)
315
+ headlinks[:tail] = links[:tail]
316
+ putdata(headlinks,headlink_file)
317
+ else
318
+ putdata(links[:tail],@cache_head)
319
+ end
320
+
321
+ if links[:tail]
322
+ taillink_file = File.join(path_for_hash(links[:tail]),"#{links[:tail]}.inf")
323
+ taillinks = getdata(taillink_file,false)
324
+ taillinks[:head] = links[:head]
325
+ putdata(taillinks,taillink_file)
326
+ else
327
+ putdata(links[:head],@cache_tail)
328
+ end
329
+ end
330
+
331
+ # Get the current head of the list.
332
+ current_head = getdata(@cache_head,false)
333
+ current_key_hash = hash_for_key(key)
334
+ unless current_key_hash == current_head
335
+ # Get the current tail of the list.
336
+ current_tail = getdata(@cache_tail,false)
337
+ # Write the link file for the new head.
338
+ putdata({:head => nil, :tail => current_head},linkfile_for_key(key))
339
+ # Change the cache_head so it points to the new head.
340
+ putdata(current_key_hash,@cache_head)
341
+ # If the tail wasn't pointint to anything, the list was empty.
342
+ # Point it to this record.
343
+ putdata(current_key_hash,@cache_tail) unless current_tail
344
+ # Change the old head so that it points to the new element as its head.
345
+ if current_head
346
+ taillink_file = File.join(path_for_hash(current_head),"#{current_head}.inf")
347
+ taillinks = getdata(taillink_file,false)
348
+ taillinks[:head] = current_key_hash
349
+ putdata(taillinks,taillink_file)
350
+ end
351
+ end
352
+ end
353
+ end
354
+
355
+ # Set the element of the cache identified by the given key.
356
+
357
+ def []=(key, val)
358
+ lock_cache do
359
+ if !@bypass_transactions and @transaction_cache.length > 0
360
+ @transaction_cache.last[key] = val
361
+ else
362
+ attach(key, val)
363
+ mxsz = getdata(@cache_maxsize,false)
364
+ if mxsz > 0
365
+ prune while getdata(@cache_count,false) > mxsz
366
+ end
367
+ maxttl = getdata(@cache_maxttl,false)
368
+ if maxttl
369
+ expiration = Time.now.to_i - maxttl
370
+ prune while (getdata(@cache_count,false) > 0) && (File::stat(datafile_for_key(getdata(@cache_tail,false))).mtime.to_i < expiration)
371
+ end
372
+ end
373
+ end
374
+ end
375
+
376
+ # Allows one to set the maximum size of the cache queue. If the queue
377
+ # is currently larger than the size that it is being set to, elements
378
+ # will be expired until the queue is at the maximum size.
379
+
380
+ def size=(max)
381
+ lock_cache do
382
+ prune while getdata(@cache_count,false) > max
383
+ putdata(max,@cache_maxsize)
384
+ end
385
+ end
386
+ alias maxsize= size=
387
+
388
+ # Return the maximum size of the cache.
389
+ def maxsize
390
+ getdata(@cache_maxsize)
391
+ end
392
+
393
+ # Return the current size of the cache.
394
+ def size
395
+ getdata(@cache_count)
396
+ end
397
+
398
+ def ttl=(newttl)
399
+ newttl = newttl ? newttl.to_i : nil
400
+ if @maxttl
401
+ lock_cache do
402
+ expiration = Time.now.to_i - newttl
403
+ prune while (getdata(@cache_count,false) > 0) && (File::stat(datafile_for_key(getdata(@cache_tail,false))).mtime.to_i < expiration)
404
+ end
405
+ end
406
+ putdata(newttl,@cache_maxttl)
407
+ end
408
+ alias maxttl= ttl=
409
+
410
+ def ttl
411
+ getdata(@maxttl)
412
+ end
413
+
414
+ # Return a copy of current set of keys to cache elements.
415
+ def queue
416
+ r = []
417
+ #Find::find(@cache_dir) do |p|
418
+ # if p =~ /#{File::SEPARATOR}[^#{File::SEPARATOR}]+.key$/
419
+ # r.push getdata(p)
420
+ # end
421
+ #end
422
+ n = getdata(@cache_head)
423
+ loop do
424
+ links = getdata(File.join(path_for_hash(n),"#{n}.inf"))
425
+ r.push getdata(File.join(path_for_hash(n),"#{n}.key"))
426
+ break if links[:tail].nil?
427
+ n = links[:tail]
428
+ end
429
+ r
430
+ end
431
+
432
+ def transaction(&b)
433
+ Thread.critical = true
434
+ if @transaction_lock[0] and @transaction_cache.length > 0
435
+ if Thread.current == @transaction_lock[0]
436
+ Thread.critical = false
437
+ inner_transaction(b)
438
+ return true
439
+ end
440
+ else
441
+ @transaction_lock[0] = Thread.current
442
+ end
443
+ Thread.critical = false
444
+ @transaction_lock[1].synchronize {inner_transaction(b)}
445
+ @transaction_lock[0] = nil
446
+ end
447
+
448
+ def commit(final = false)
449
+ Thread.critical = true
450
+ transactions = @transaction_cache.pop
451
+ q = transactions.queue
452
+ (q.length - 1).downto(0) do |x|
453
+ k = q[x]
454
+ v = transactions[k]
455
+ if v.is_a?(DeletedValue)
456
+ @bypass_transactions = true
457
+ self.delete(k)
458
+ @bypass_transactions = false
459
+ else
460
+ @bypass_transactions = true
461
+ self[k] = transactions[k]
462
+ @bypass_transactions = false
463
+ end
464
+ end
465
+ unless final
466
+ @transaction_cache.push Iowa::Caches::LRUCache.new({:maxsize => 4294967296})
467
+ end
468
+ Thread.critical = false
469
+ end
470
+
471
+ def rollback
472
+ Thread.critical = true
473
+ @transaction_cache.pop
474
+ @transaction_cache.push Iowa::Caches::LRUCache.new({:maxsize => 4294967296})
475
+ Thread.critical = true
476
+ end
477
+
478
+ private
479
+
480
+ def inner_transaction(blk)
481
+ @transaction_cache.push Iowa::Caches::LRUCache.new({:maxsize => 4294967296})
482
+ blk.call
483
+ Thread.critical = true
484
+ commit(true)
485
+ Thread.critical = false
486
+ end
487
+
488
+ def transaction_cache_include?(key)
489
+ @transaction_cache.each do |tc|
490
+ return true if tc.include? key
491
+ end
492
+ false
493
+ end
494
+
495
+ def transaction_cache_get(key)
496
+ (@transaction_cache.length - 1).downto(0) do |x|
497
+ return @transaction_cache[x][key] if @transaction_cache[x].include?(key)
498
+ end
499
+ nil
500
+ end
501
+
502
+ def lock_cache
503
+ Thread.critical = true
504
+ transaction_in_progress = (@transaction_lock[0] and @transaction_cache.length > 0) ? true : false
505
+ @transaction_lock[0] = Thread.current unless transaction_in_progress
506
+ Thread.critical = false if transaction_in_progress
507
+ @transaction_lock[1].synchronize_unless(@transaction_lock[0] == Thread.current) do
508
+ Thread.critical = false unless transaction_in_progress
509
+ unless @locked
510
+ begin
511
+ if @use_lockfile
512
+ @lockfile.lock {@locked = true; yield}
513
+ else
514
+ @mutex.synchronize {@locked = true; yield}
515
+ end
516
+ ensure
517
+ @locked = false
518
+ end
519
+ else
520
+ yield
521
+ end
522
+ end
523
+ @transaction_lock[0] = nil unless transaction_in_progress
524
+ end
525
+
526
+ def create_head_and_tail_files
527
+ putdata(nil,@cache_head)
528
+ putdata(nil,@cache_tail)
529
+ putdata(0,@cache_count)
530
+ putdata(@max,@cache_maxsize)
531
+ putdata(@maxttl,@cache_maxttl)
532
+ end
533
+
534
+ def hash_for_key(key)
535
+ k = Marshal.dump(key)
536
+ Digest::SHA512.hexdigest(Marshal.dump(key))
537
+ end
538
+
539
+ def path_for_hash(hash)
540
+ # Take the hash key and break it apart by bucket_depth and bucket_width
541
+ # to return the path to the directory that should contain the
542
+ # cache element.
543
+ File.join(@cache_dir,@bucket_depth_array.collect {|d| hash[(d * @bucket_width),@bucket_width]})
544
+ end
545
+
546
+ def datafile_for_key(key)
547
+ h = hash_for_key(key)
548
+ File.join(path_for_hash(h),"#{h}.dat")
549
+ end
550
+
551
+ def linkfile_for_key(key)
552
+ h = hash_for_key(key)
553
+ File.join(path_for_hash(h),"#{h}.inf")
554
+ end
555
+
556
+ def keyfile_for_key(key)
557
+ h = hash_for_key(key)
558
+ File.join(path_for_hash(h),"#{h}.key")
559
+ end
560
+
561
+ def getdata(filename,do_lock = true)
562
+ r = nil
563
+ if do_lock
564
+ lock_cache do
565
+ if FileTest::exist?(filename)
566
+ File.open(filename) {|fh| r = Marshal.load(fh)}
567
+ end
568
+ end
569
+ else
570
+ if FileTest::exist?(filename)
571
+ File.open(filename) {|fh| r = Marshal.load(fh)}
572
+ end
573
+ end
574
+ r
575
+ end
576
+
577
+ def getdata_worker(filename)
578
+ if FileTest::exist?(filename)
579
+ File.open(filename) {|fh| Marshal.load(fh)}
580
+ else
581
+ nil
582
+ end
583
+ end
584
+
585
+ def putdata(value,filename,do_lock = true)
586
+ if do_lock
587
+ lock_cache do
588
+ putdata_worker(value,filename)
589
+ end
590
+ else
591
+ putdata_worker(value,filename)
592
+ end
593
+ end
594
+
595
+ def putdata_worker(value,filename)
596
+ FileUtils.mkdir_p(File::dirname(filename)) unless FileTest.exist?(File::dirname(filename))
597
+ File.open(filename,'w') {|fh| Marshal.dump(value,fh)}
598
+ end
599
+
600
+ def set_cachefile_paths
601
+ @cache_head = File.join(@cache_dir,'cache_head.inf')
602
+ @cache_tail = File.join(@cache_dir,'cache_tail.inf')
603
+ @cache_count = File.join(@cache_dir,'cache_count.inf')
604
+ @cache_maxsize = File.join(@cache_dir,'cache_maxsize.inf')
605
+ @cache_maxttl = File.join(@cache_dir,'cache_maxttl.inf')
606
+ end
607
+ end
608
+ end
609
+ end