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.
- checksums.yaml +7 -0
- data/CONTRIBUTORS +14 -0
- data/README.md +23 -0
- data/RELEASE_NOTES +77 -0
- data/ToDo +21 -0
- data/components/CRUDList/CRUDList.html +13 -0
- data/components/CRUDList/CRUDList.iwa +136 -0
- data/components/Content/Content.html +0 -0
- data/components/Content/Content.iwa +143 -0
- data/components/Content/example/README +9 -0
- data/components/Content/example/cgi/iowa.cgi +10 -0
- data/components/Content/example/demo.rb +30 -0
- data/components/Content/example/doc/index.html +7 -0
- data/components/Content/example/iowa/Content.html +1 -0
- data/components/Content/example/iowa/Content.iwa +1 -0
- data/components/Content/example/iowa/Main.html +6 -0
- data/components/Content/example/iowa/Main.iwa +3 -0
- data/components/Content/example/iowa/_content/body +7 -0
- data/components/Content/example/iowa/_content/body2 +3 -0
- data/components/Content/example/iowa/_content/title +2 -0
- data/components/Content/example/iowa/app.cnf +8 -0
- data/components/Content/example/iowa/app.rb +8 -0
- data/components/Content/example/webrick.rb +38 -0
- data/components/Include/Include.html +1 -0
- data/components/Include/Include.iwa +30 -0
- data/components/Include/readme +5 -0
- data/components/JumpTo/JumpTo.html +8 -0
- data/components/JumpTo/JumpTo.iwa +8 -0
- data/components/JumpTo/readme +6 -0
- data/doc/Architecture.txt +6 -0
- data/doc/History.txt +33 -0
- data/doc/StandardDispatcher.txt +19 -0
- data/examples/blog/README +1 -0
- data/examples/hello_world/README +17 -0
- data/examples/hello_world/htdocs/hello_world_html.html +24 -0
- data/examples/hello_world/htdocs/hello_world_ruby.html +41 -0
- data/examples/hello_world/iowa/HelloWorld.html +14 -0
- data/examples/hello_world/iowa/HelloWorld.iwa +31 -0
- data/examples/hello_world/iowa/Index.html +16 -0
- data/examples/hello_world/iowa/Index.iwa +5 -0
- data/examples/hello_world/iowa/iowa_hello_world.cnf +19 -0
- data/examples/hello_world/iowa/iowa_hello_world.rb +5 -0
- data/examples/hello_world/iowa/mapfile.cnf +6 -0
- data/examples/hw1/iowa/Main.html +1 -0
- data/examples/hw1/iowa/README +9 -0
- data/examples/hw1/iowa/hw.rb +4 -0
- data/examples/hw2/iowa/Main.html +10 -0
- data/examples/hw2/iowa/Main.iwa +7 -0
- data/examples/hw2/iowa/README +16 -0
- data/examples/hw2/iowa/hw.rb +4 -0
- data/examples/hw3/iowa/Main.html +11 -0
- data/examples/hw3/iowa/Main.iwa +7 -0
- data/examples/hw3/iowa/README +22 -0
- data/examples/hw3/iowa/hw.rb +4 -0
- data/examples/hw4/iowa/Greetings.html +10 -0
- data/examples/hw4/iowa/Greetings.iwa +9 -0
- data/examples/hw4/iowa/Main.html +12 -0
- data/examples/hw4/iowa/Main.iwa +10 -0
- data/examples/hw4/iowa/README +28 -0
- data/examples/hw4/iowa/hw.rb +4 -0
- data/examples/hw5/iowa/Footer.html +2 -0
- data/examples/hw5/iowa/Greetings.html +4 -0
- data/examples/hw5/iowa/Greetings.iwa +12 -0
- data/examples/hw5/iowa/Header.html +6 -0
- data/examples/hw5/iowa/Main.html +12 -0
- data/examples/hw5/iowa/Main.iwa +13 -0
- data/examples/hw5/iowa/README +16 -0
- data/examples/hw5/iowa/hw.rb +4 -0
- data/examples/template_server/iowa/Content.iwa +121 -0
- data/examples/template_server/iowa/Content.view +0 -0
- data/examples/template_server/iowa/DBContentDispatcher.rb +112 -0
- data/examples/template_server/iowa/DBContentPage.html +3 -0
- data/examples/template_server/iowa/DBContentPage.iwa +85 -0
- data/examples/template_server/iowa/app.cnf +13 -0
- data/examples/template_server/iowa/app.rb +5 -0
- data/ext/Classifier/classifier.c +256 -0
- data/ext/Classifier/ext_help.h +14 -0
- data/ext/Classifier/extconf.rb +5 -0
- data/ext/Classifier/tst.h +40 -0
- data/ext/Classifier/tst_cleanup.c +24 -0
- data/ext/Classifier/tst_delete.c +146 -0
- data/ext/Classifier/tst_grow_node_free_list.c +38 -0
- data/ext/Classifier/tst_init.c +41 -0
- data/ext/Classifier/tst_insert.c +192 -0
- data/ext/Classifier/tst_search.c +68 -0
- data/ext/http11/README +11 -0
- data/ext/http11/ext_help.h +15 -0
- data/ext/http11/extconf.rb +5 -0
- data/ext/http11/http11.c +534 -0
- data/ext/http11/http11.c.dif +422 -0
- data/ext/http11/http11_parser.c +1243 -0
- data/ext/http11/http11_parser.c.dif +193 -0
- data/ext/http11/http11_parser.h +49 -0
- data/ext/http11/http11_parser.h.dif +20 -0
- data/ext/http11/http11_parser.rl +192 -0
- data/ext/httpmachine/Makefile +149 -0
- data/ext/httpmachine/extconf.rb +33 -0
- data/ext/httpmachine/http.cpp +430 -0
- data/ext/httpmachine/http.h +156 -0
- data/ext/httpmachine/rubyhttp.cpp +165 -0
- data/external/mime-types/LICENCE +18 -0
- data/external/mime-types/README +46 -0
- data/external/mime-types/doc/classes/MIME.html +120 -0
- data/external/mime-types/doc/classes/MIME/InvalidContentType.html +119 -0
- data/external/mime-types/doc/classes/MIME/Type.html +866 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000010.html +22 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000011.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000012.html +19 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000013.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000014.html +26 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000015.html +33 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000016.html +27 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000017.html +35 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000018.html +34 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000019.html +24 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000020.html +38 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000021.html +22 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000022.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000023.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000024.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000025.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000026.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000027.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000028.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000029.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000030.html +19 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000031.html +26 -0
- data/external/mime-types/doc/classes/MIME/Types.html +459 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000001.html +19 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000002.html +32 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000003.html +21 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000004.html +18 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000005.html +26 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000006.html +18 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000007.html +18 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000008.html +18 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000009.html +18 -0
- data/external/mime-types/doc/created.rid +1 -0
- data/external/mime-types/doc/files/ChangeLog.html +320 -0
- data/external/mime-types/doc/files/README.html +145 -0
- data/external/mime-types/doc/files/lib/mime/types_rb.html +101 -0
- data/external/mime-types/doc/fr_class_index.html +30 -0
- data/external/mime-types/doc/fr_file_index.html +29 -0
- data/external/mime-types/doc/fr_method_index.html +57 -0
- data/external/mime-types/doc/index.html +24 -0
- data/external/mime-types/doc/rdoc-style.css +208 -0
- data/external/mime-types/lib/mime/types.rb +1558 -0
- data/external/package.rb +672 -0
- data/external/test_support.rb +95 -0
- data/external/tmail/README +7 -0
- data/external/tmail/tmail.rb +4 -0
- data/external/tmail/tmail/address.rb +222 -0
- data/external/tmail/tmail/base64.rb +52 -0
- data/external/tmail/tmail/compat.rb +39 -0
- data/external/tmail/tmail/config.rb +50 -0
- data/external/tmail/tmail/encode.rb +447 -0
- data/external/tmail/tmail/header.rb +895 -0
- data/external/tmail/tmail/info.rb +14 -0
- data/external/tmail/tmail/loader.rb +1 -0
- data/external/tmail/tmail/mail.rb +869 -0
- data/external/tmail/tmail/mailbox.rb +386 -0
- data/external/tmail/tmail/mbox.rb +1 -0
- data/external/tmail/tmail/net.rb +260 -0
- data/external/tmail/tmail/obsolete.rb +123 -0
- data/external/tmail/tmail/parser.rb +1475 -0
- data/external/tmail/tmail/parser.y +372 -0
- data/external/tmail/tmail/port.rb +356 -0
- data/external/tmail/tmail/scanner.rb +17 -0
- data/external/tmail/tmail/scanner_r.rb +243 -0
- data/external/tmail/tmail/stringio.rb +256 -0
- data/external/tmail/tmail/textutils.rb +197 -0
- data/external/tmail/tmail/tmail.rb +1 -0
- data/external/tmail/tmail/utils.rb +23 -0
- data/external/win32-process/README +133 -0
- data/external/win32-process/lib/win32/process.rb +561 -0
- data/external/windows-pr/README +145 -0
- data/external/windows-pr/doc/conversion_guide.txt +25 -0
- data/external/windows-pr/lib/windows/clipboard.rb +72 -0
- data/external/windows-pr/lib/windows/console.rb +323 -0
- data/external/windows-pr/lib/windows/device_io.rb +88 -0
- data/external/windows-pr/lib/windows/directory.rb +80 -0
- data/external/windows-pr/lib/windows/error.rb +313 -0
- data/external/windows-pr/lib/windows/eventlog.rb +120 -0
- data/external/windows-pr/lib/windows/file.rb +349 -0
- data/external/windows-pr/lib/windows/filesystem.rb +16 -0
- data/external/windows-pr/lib/windows/handle.rb +31 -0
- data/external/windows-pr/lib/windows/library.rb +76 -0
- data/external/windows-pr/lib/windows/limits.rb +13 -0
- data/external/windows-pr/lib/windows/memory.rb +117 -0
- data/external/windows-pr/lib/windows/msvcrt/buffer.rb +48 -0
- data/external/windows-pr/lib/windows/msvcrt/file.rb +18 -0
- data/external/windows-pr/lib/windows/msvcrt/string.rb +46 -0
- data/external/windows-pr/lib/windows/national.rb +557 -0
- data/external/windows-pr/lib/windows/path.rb +296 -0
- data/external/windows-pr/lib/windows/pipe.rb +77 -0
- data/external/windows-pr/lib/windows/process.rb +171 -0
- data/external/windows-pr/lib/windows/registry.rb +238 -0
- data/external/windows-pr/lib/windows/security.rb +89 -0
- data/external/windows-pr/lib/windows/service.rb +183 -0
- data/external/windows-pr/lib/windows/shell.rb +88 -0
- data/external/windows-pr/lib/windows/sound.rb +52 -0
- data/external/windows-pr/lib/windows/synchronize.rb +161 -0
- data/external/windows-pr/lib/windows/system_info.rb +70 -0
- data/external/windows-pr/lib/windows/unicode.rb +138 -0
- data/external/windows-pr/lib/windows/window.rb +22 -0
- data/iowa.gemspec +45 -0
- data/microprojects/DiskCache/LICENSE +28 -0
- data/microprojects/DiskCache/README +17 -0
- data/microprojects/DiskCache/external/package.rb +608 -0
- data/microprojects/DiskCache/external/test_support.rb +8 -0
- data/microprojects/DiskCache/setup.rb +22 -0
- data/microprojects/DiskCache/src/iowa/Association.rb +67 -0
- data/microprojects/DiskCache/src/iowa/Constants.rb +159 -0
- data/microprojects/DiskCache/src/iowa/DiskStore.rb +377 -0
- data/microprojects/DiskCache/src/iowa/Hash.rb +63 -0
- data/microprojects/DiskCache/src/iowa/Lockfile.rb +575 -0
- data/microprojects/DiskCache/src/iowa/Mutex.rb +142 -0
- data/microprojects/DiskCache/src/iowa/caches/DiskCache.rb +605 -0
- data/microprojects/DiskCache/src/iowa/caches/LRUCache.rb +287 -0
- data/microprojects/DiskCache/test/TC_DiskCache.rb +218 -0
- data/microprojects/LRUCache/LICENSE +28 -0
- data/microprojects/LRUCache/README +13 -0
- data/microprojects/LRUCache/external/package.rb +608 -0
- data/microprojects/LRUCache/external/test_support.rb +8 -0
- data/microprojects/LRUCache/setup.rb +22 -0
- data/microprojects/LRUCache/src/iowa/Association.rb +57 -0
- data/microprojects/LRUCache/src/iowa/Constants.rb +159 -0
- data/microprojects/LRUCache/src/iowa/Hash.rb +63 -0
- data/microprojects/LRUCache/src/iowa/Mutex.rb +129 -0
- data/microprojects/LRUCache/src/iowa/caches/LRUCache.rb +287 -0
- data/microprojects/LRUCache/test/TC_LRUCache.rb +65 -0
- data/microprojects/LinkedList/LICENSE +28 -0
- data/microprojects/LinkedList/README +13 -0
- data/microprojects/LinkedList/external/package.rb +608 -0
- data/microprojects/LinkedList/external/test_support.rb +8 -0
- data/microprojects/LinkedList/setup.rb +22 -0
- data/microprojects/LinkedList/src/iowa/LinkedList.rb +165 -0
- data/microprojects/LinkedList/test/TC_LinkedList.rb +42 -0
- data/microprojects/README +8 -0
- data/setup.rb +116 -0
- data/share/iowa/app_skeleton/Main.html +8 -0
- data/share/iowa/app_skeleton/Main.iwa +15 -0
- data/share/iowa/app_skeleton/app.cnf +48 -0
- data/share/iowa/app_skeleton/app.rb +58 -0
- data/share/iowa/app_skeleton/models/model.rb +49 -0
- data/src/ihc.rb +223 -0
- data/src/iowa.cgi +29 -0
- data/src/iowa.rb +637 -0
- data/src/iowa/AbstractCache.rb +96 -0
- data/src/iowa/AcceptLanguage.rb +76 -0
- data/src/iowa/Application.rb +928 -0
- data/src/iowa/ApplicationStats.rb +72 -0
- data/src/iowa/Association.rb +67 -0
- data/src/iowa/BindingsParser.rb +62 -0
- data/src/iowa/Breakpoint.rb +273 -0
- data/src/iowa/CSS.rb +564 -0
- data/src/iowa/Client.rb +192 -0
- data/src/iowa/Component.rb +405 -0
- data/src/iowa/ComponentProxy.rb +26 -0
- data/src/iowa/Config.rb +21 -0
- data/src/iowa/Constants.rb +226 -0
- data/src/iowa/Context.rb +218 -0
- data/src/iowa/ContextLogger.rb +16 -0
- data/src/iowa/DbPool.rb +222 -0
- data/src/iowa/DetachedComponent.rb +18 -0
- data/src/iowa/Dispatcher.rb +27 -0
- data/src/iowa/DynamicElements.rb +471 -0
- data/src/iowa/Element.rb +100 -0
- data/src/iowa/Email.rb +287 -0
- data/src/iowa/Extensions/AllExtensions.rb +4 -0
- data/src/iowa/Extensions/Class.rb +94 -0
- data/src/iowa/Extensions/Date.rb +88 -0
- data/src/iowa/Extensions/DateTime.rb +88 -0
- data/src/iowa/Extensions/Hash.rb +22 -0
- data/src/iowa/Extensions/Kernel.rb +6 -0
- data/src/iowa/Extensions/Numeric.rb +47 -0
- data/src/iowa/Extensions/Object.rb +11 -0
- data/src/iowa/Extensions/String.rb +60 -0
- data/src/iowa/Extensions/Time.rb +89 -0
- data/src/iowa/Extensions/TimeExtensions.rb +6 -0
- data/src/iowa/Form.rb +368 -0
- data/src/iowa/Hash.rb +85 -0
- data/src/iowa/ISAAC.rb +175 -0
- data/src/iowa/ImageSize.rb +279 -0
- data/src/iowa/IowaComponentMixins.rb +7 -0
- data/src/iowa/JSON-lexer.rb +296 -0
- data/src/iowa/JSON-objects.rb +201 -0
- data/src/iowa/KeyValueCoding.rb +91 -0
- data/src/iowa/LinkedList.rb +175 -0
- data/src/iowa/Loader.rb +22 -0
- data/src/iowa/Lockfile.rb +575 -0
- data/src/iowa/Logger.rb +74 -0
- data/src/iowa/Monkey.rb +20 -0
- data/src/iowa/Mutex.rb +142 -0
- data/src/iowa/Policy.rb +70 -0
- data/src/iowa/Pool.rb +243 -0
- data/src/iowa/PrettyException.rb +1091 -0
- data/src/iowa/Request.rb +244 -0
- data/src/iowa/Response.rb +133 -0
- data/src/iowa/Session.rb +354 -0
- data/src/iowa/SessionStats.rb +78 -0
- data/src/iowa/String.rb +65 -0
- data/src/iowa/Tag.rb +101 -0
- data/src/iowa/TemplateParser.rb +236 -0
- data/src/iowa/Util.rb +314 -0
- data/src/iowa/Webcache.rb +122 -0
- data/src/iowa/caches/BiLevelCache.rb +65 -0
- data/src/iowa/caches/ClassLimitedCache.rb +67 -0
- data/src/iowa/caches/DiskCache.rb +609 -0
- data/src/iowa/caches/DiskStore.rb +380 -0
- data/src/iowa/caches/LRUCache-alternative.rb +155 -0
- data/src/iowa/caches/LRUCache.rb +290 -0
- data/src/iowa/caches/SimpleLRUCache.rb +112 -0
- data/src/iowa/dispatchers/StandardDispatcher.rb +396 -0
- data/src/iowa/dispatchers/StandardDispatcherWithClassifier.rb +93 -0
- data/src/iowa/js/iowa_jsonrpc.js +381 -0
- data/src/iowa/js/jsonrpc.js +187 -0
- data/src/iowa/js/jsonrpc_async.js +261 -0
- data/src/iowa/loaders/DiskLoader.rb +50 -0
- data/src/iowa/loggers/Analogger.rb +54 -0
- data/src/iowa/loggers/AsyncLogger.rb +54 -0
- data/src/iowa/loggers/BitBucket.rb +38 -0
- data/src/iowa/loggers/Log4R.rb +13 -0
- data/src/iowa/loggers/Log4rLogger.rb +48 -0
- data/src/iowa/loggers/Logger.rb +29 -0
- data/src/iowa/loggers/RubyLogger.rb +9 -0
- data/src/iowa/pools/DBConnectionPool.rb +53 -0
- data/src/iowa/request/Apache.rb +90 -0
- data/src/iowa/request/EMHybrid.rb +59 -0
- data/src/iowa/request/ENV.rb +80 -0
- data/src/iowa/request/FCGI.rb +68 -0
- data/src/iowa/request/HTTPMachine.rb +75 -0
- data/src/iowa/request/Mongrel.rb +68 -0
- data/src/iowa/request/WEBrick.rb +48 -0
- data/src/iowa/version.rb +3 -0
- data/src/iowa/webrick/HTTPServer.rb +43 -0
- data/src/iowa/webrick/WEBrickServlet.rb +28 -0
- data/src/iowa_fcgi_handler.rb +101 -0
- data/src/iowa_httpmachine.rb +141 -0
- data/src/iowa_hybrid.rb +193 -0
- data/src/iowa_hybrid_cluster.rb +231 -0
- data/src/iowa_mongrel.rb +136 -0
- data/src/iowa_webrick.rb +194 -0
- data/src/iowa_webrick_legacy.rb +104 -0
- data/src/mod_iowa.rb +104 -0
- data/tcss.rb +61 -0
- data/test/README.windows +12 -0
- data/test/TC_AcceptLanguage.rb +61 -0
- data/test/TC_AppConfig.rb +43 -0
- data/test/TC_AppConfig/cgi/iowa.cgi +7 -0
- data/test/TC_AppConfig/doc/index.html +1 -0
- data/test/TC_AppConfig/iowa/Main.html +4 -0
- data/test/TC_AppConfig/iowa/Main.iwa +17 -0
- data/test/TC_AppConfig/iowa/README +1 -0
- data/test/TC_AppConfig/iowa/app.cnf +19 -0
- data/test/TC_AppConfig/iowa/app.rb +8 -0
- data/test/TC_AppConfig/webrick.rb +38 -0
- data/test/TC_Association.rb +29 -0
- data/test/TC_BiLevelCache.rb +71 -0
- data/test/TC_CGI_Adaptor.rb +55 -0
- data/test/TC_CGI_Adaptor/cgi/iowa.cgi +7 -0
- data/test/TC_CGI_Adaptor/doc/index.html +1 -0
- data/test/TC_CGI_Adaptor/iowa/Main.html +8 -0
- data/test/TC_CGI_Adaptor/iowa/Main.iwa +14 -0
- data/test/TC_CGI_Adaptor/iowa/README +1 -0
- data/test/TC_CGI_Adaptor/iowa/app.cnf +8 -0
- data/test/TC_CGI_Adaptor/iowa/app.rb +8 -0
- data/test/TC_CGI_Adaptor/webrick.rb +38 -0
- data/test/TC_CSS.rb +660 -0
- data/test/TC_ClassLimitedCache.rb +89 -0
- data/test/TC_Classifier.rb +80 -0
- data/test/TC_DbPool.rb +127 -0
- data/test/TC_DiskCache.rb +218 -0
- data/test/TC_Hybrid.rb +58 -0
- data/test/TC_Hybrid/doc/thing.txt +1 -0
- data/test/TC_Hybrid/iowa/Main.html +3 -0
- data/test/TC_Hybrid/iowa/Main.iwa +7 -0
- data/test/TC_Hybrid/iowa/NewPage.html +1 -0
- data/test/TC_Hybrid/iowa/NewPage.iwa +5 -0
- data/test/TC_Hybrid/iowa/app.cnf +10 -0
- data/test/TC_Hybrid/iowa/app.rb +5 -0
- data/test/TC_IOWAFunctions/doc/Ajax1.html +1 -0
- data/test/TC_IOWAFunctions/doc/Ajax1.iwa +1 -0
- data/test/TC_IOWAFunctions/doc/index.html +1 -0
- data/test/TC_IOWAFunctions/doc/js/dojo.js +9686 -0
- data/test/TC_IOWAFunctions/iowa/Ajax1.html +40 -0
- data/test/TC_IOWAFunctions/iowa/Ajax1.iwa +23 -0
- data/test/TC_IOWAFunctions/iowa/AjaxWidget.iwa +19 -0
- data/test/TC_IOWAFunctions/iowa/AjaxWidget.view +22 -0
- data/test/TC_IOWAFunctions/iowa/DanielTest.html +9 -0
- data/test/TC_IOWAFunctions/iowa/DanielTest.iwa +10 -0
- data/test/TC_IOWAFunctions/iowa/IntervalWidget.html +1 -0
- data/test/TC_IOWAFunctions/iowa/IntervalWidget.iwa +14 -0
- data/test/TC_IOWAFunctions/iowa/Main.html +1 -0
- data/test/TC_IOWAFunctions/iowa/NestedRepeat1.html +12 -0
- data/test/TC_IOWAFunctions/iowa/NestedRepeat1.iwa +24 -0
- data/test/TC_IOWAFunctions/iowa/RPCResponse.iwa +7 -0
- data/test/TC_IOWAFunctions/iowa/RPCResponse.view +1 -0
- data/test/TC_IOWAFunctions/iowa/Repeat1.iwa +31 -0
- data/test/TC_IOWAFunctions/iowa/Repeat1.view +9 -0
- data/test/TC_IOWAFunctions/iowa/Repeat2.iwa +32 -0
- data/test/TC_IOWAFunctions/iowa/Repeat2.view +11 -0
- data/test/TC_IOWAFunctions/iowa/Repeat3.iwa +44 -0
- data/test/TC_IOWAFunctions/iowa/Repeat3.view +18 -0
- data/test/TC_IOWAFunctions/iowa/TesCon.html +1 -0
- data/test/TC_IOWAFunctions/iowa/TesCon.iwa +5 -0
- data/test/TC_IOWAFunctions/iowa/app.cnf +19 -0
- data/test/TC_IOWAFunctions/iowa/app.rb +9 -0
- data/test/TC_IOWAFunctions/iowa/mapfile.cnf +8 -0
- data/test/TC_ISAAC.rb +52 -0
- data/test/TC_ImageSize.rb +84 -0
- data/test/TC_ImageSize/img.bmp +0 -0
- data/test/TC_ImageSize/img.gif +0 -0
- data/test/TC_ImageSize/img.jpg +0 -0
- data/test/TC_ImageSize/img.pcx +0 -0
- data/test/TC_ImageSize/img.pgm +7144 -0
- data/test/TC_ImageSize/img.png +0 -0
- data/test/TC_ImageSize/img.ppm +0 -0
- data/test/TC_ImageSize/img.psd +0 -0
- data/test/TC_ImageSize/img.tiff +0 -0
- data/test/TC_ImageSize/img.xbm +22 -0
- data/test/TC_KeyValueCoding.rb +35 -0
- data/test/TC_LRUCache.rb +296 -0
- data/test/TC_LinkedList.rb +46 -0
- data/test/TC_Lockfile.rb +106 -0
- data/test/TC_Minimal.rb +45 -0
- data/test/TC_Minimal/app.cnf +8 -0
- data/test/TC_Minimal/cgi-bin/iowa.cgi +11 -0
- data/test/TC_Minimal/doc/index.html +1 -0
- data/test/TC_Minimal/iowa/Main.html +1 -0
- data/test/TC_Minimal/iowa/README +1 -0
- data/test/TC_Minimal/iowa/app.rb +3 -0
- data/test/TC_Minimal/webrick.rb +38 -0
- data/test/TC_Mongrel.rb +58 -0
- data/test/TC_Mongrel/doc/thing.txt +1 -0
- data/test/TC_Mongrel/iowa/Main.html +3 -0
- data/test/TC_Mongrel/iowa/Main.iwa +7 -0
- data/test/TC_Mongrel/iowa/NewPage.html +1 -0
- data/test/TC_Mongrel/iowa/NewPage.iwa +5 -0
- data/test/TC_Mongrel/iowa/app.cnf +10 -0
- data/test/TC_Mongrel/iowa/app.rb +5 -0
- data/test/TC_NoSubclass.rb +56 -0
- data/test/TC_NoSubclass/cgi/iowa.cgi +7 -0
- data/test/TC_NoSubclass/doc/index.html +1 -0
- data/test/TC_NoSubclass/iowa/Main.html +8 -0
- data/test/TC_NoSubclass/iowa/Main.iwa +14 -0
- data/test/TC_NoSubclass/iowa/README +1 -0
- data/test/TC_NoSubclass/iowa/app.cnf +8 -0
- data/test/TC_NoSubclass/iowa/app.rb +5 -0
- data/test/TC_NoSubclass/webrick.rb +38 -0
- data/test/TC_Pool.rb +139 -0
- data/test/TC_RenderedCache/doc/thing.txt +1 -0
- data/test/TC_RenderedCache/iowa/BigPage.html +1 -0
- data/test/TC_RenderedCache/iowa/BigPage.iwa +12 -0
- data/test/TC_RenderedCache/iowa/Main.html +3 -0
- data/test/TC_RenderedCache/iowa/Main.iwa +7 -0
- data/test/TC_RenderedCache/iowa/NewPage.html +1 -0
- data/test/TC_RenderedCache/iowa/NewPage.iwa +11 -0
- data/test/TC_RenderedCache/iowa/app.cnf +13 -0
- data/test/TC_RenderedCache/iowa/app.rb +5 -0
- data/test/TC_RenderedCache/iowa/mapfile.map +4 -0
- data/test/TC_ResourceURL.rb +73 -0
- data/test/TC_ResourceURL/iowa/Main.html +2 -0
- data/test/TC_ResourceURL/iowa/Main.iwa +10 -0
- data/test/TC_ResourceURL/iowa/app.cnf +10 -0
- data/test/TC_ResourceURL/iowa/app.rb +5 -0
- data/test/TC_SimpleDetached.rb +41 -0
- data/test/TC_StandardDispatcher.rb +362 -0
- data/test/TC_StandardDispatcherWithClassifier.rb +358 -0
- data/test/TC_String.rb +24 -0
- data/test/TC_Tag.rb +41 -0
- data/test/TC_Webrick.rb +56 -0
- data/test/TC_Webrick/doc/thing.txt +1 -0
- data/test/TC_Webrick/iowa/Main.html +3 -0
- data/test/TC_Webrick/iowa/Main.iwa +7 -0
- data/test/TC_Webrick/iowa/NewPage.html +1 -0
- data/test/TC_Webrick/iowa/NewPage.iwa +5 -0
- data/test/TC_Webrick/iowa/app.cnf +10 -0
- data/test/TC_Webrick/iowa/app.rb +5 -0
- data/test/tc_template.rb +15 -0
- data/test/tests.conf +19 -0
- data/utils/CVS/Entries +3 -0
- data/utils/CVS/Repository +1 -0
- data/utils/CVS/Root +1 -0
- data/utils/QuickCert-1.0.2.tar.gz +0 -0
- data/utils/QuickCert-1.0.2/InstalledFiles +7 -0
- data/utils/QuickCert-1.0.2/MANIFEST +10 -0
- data/utils/QuickCert-1.0.2/Makefile +15 -0
- data/utils/QuickCert-1.0.2/README +56 -0
- data/utils/QuickCert-1.0.2/bin/QuickCert +355 -0
- data/utils/QuickCert-1.0.2/config.save +12 -0
- data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/README +60 -0
- data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_c.rb +26 -0
- data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_s.rb +35 -0
- data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/qc_config +21 -0
- data/utils/QuickCert-1.0.2/lib/QuickCert/defaults.rb +28 -0
- data/utils/QuickCert-1.0.2/setup.rb +1312 -0
- data/utils/iowa_apps +422 -0
- data/utils/smtp_sink.rb +9 -0
- data/utils/startup_template.cnf +27 -0
- data/utils/startup_template.rb +73 -0
- 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
|
data/src/iowa/Loader.rb
ADDED
|
@@ -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
|