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,49 @@
|
|
|
1
|
+
require 'iowa/pools/DBConnectionPool'
|
|
2
|
+
require 'kansas'
|
|
3
|
+
|
|
4
|
+
$public_dbconf = Iowa.config[Iowa::Capplication]['public_database']
|
|
5
|
+
$private_dbconf = Iowa.config[Iowa::Capplication]['private_database']
|
|
6
|
+
KSDatabase.new("dbi:#{$public_dbconf['vendor']}:#{$public_dbconf['database']}:#{$public_dbconf['host']}",$public_dbconf['user'],$public_dbconf['password']).map_all_tables
|
|
7
|
+
|
|
8
|
+
class KSDatabase
|
|
9
|
+
|
|
10
|
+
class ProductUrls
|
|
11
|
+
to_one(:product, :product_idx, :Products)
|
|
12
|
+
to_one(:product_preview, :product_idx, :ProductsPreview)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class Products
|
|
16
|
+
to_many(:product_url, :ProductUrls, :product_idx)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class ProductsPreview
|
|
20
|
+
to_many(:product_url, :ProductUrls, :product_idx)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class PubDrxDBPool < Iowa::Pool::DBConnectionPool
|
|
26
|
+
StartSize $public_dbconf['startsize']
|
|
27
|
+
MaxSize $public_dbconf['maxsize']
|
|
28
|
+
MaxAge $public_dbconf['maxage']
|
|
29
|
+
MonitorInterval $public_dbconf['monitorinterval']
|
|
30
|
+
DBClass KSDatabase
|
|
31
|
+
ConnectArgs ["dbi:#{$public_dbconf['vendor']}:#{$public_dbconf['database']}:#{$public_dbconf['host']}",$public_dbconf['user'],$public_dbconf['password']]
|
|
32
|
+
|
|
33
|
+
def getConnection(&b)
|
|
34
|
+
obtain {|h| b.call(h)}
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class PrivDrxDBPool < Iowa::Pool::DBConnectionPool
|
|
39
|
+
StartSize $private_dbconf['startsize']
|
|
40
|
+
MaxSize $private_dbconf['maxsize']
|
|
41
|
+
MaxAge $private_dbconf['maxage']
|
|
42
|
+
MonitorInterval $private_dbconf['monitorinterval']
|
|
43
|
+
DBClass KSDatabase
|
|
44
|
+
ConnectArgs ["dbi:#{$private_dbconf['vendor']}:#{$private_dbconf['database']}:#{$private_dbconf['host']}",$private_dbconf['user'],$private_dbconf['password']]
|
|
45
|
+
|
|
46
|
+
def getConnection(&b)
|
|
47
|
+
obtain {|h| b.call(h)}
|
|
48
|
+
end
|
|
49
|
+
end
|
data/src/ihc.rb
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
Iowa.runmode = :emhybridcluster
|
|
2
|
+
require 'eventmachine'
|
|
3
|
+
require 'iowa/http11'
|
|
4
|
+
require 'iowa/Client'
|
|
5
|
+
require 'iowa/request/EMHybrid'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module Iowa
|
|
9
|
+
class EMHybridClusterServer < EventMachine::Connection
|
|
10
|
+
|
|
11
|
+
MAX_HEADER = MAX_BODY = 114688
|
|
12
|
+
CEMHYBRIDCLUSTERSERVER = 'EMHybridClusterServer'.freeze
|
|
13
|
+
|
|
14
|
+
class MaxHeaderExceeded < Exception; end
|
|
15
|
+
|
|
16
|
+
def self.connect(hostname = nil,port = nil)
|
|
17
|
+
@hostname ||= hostname
|
|
18
|
+
@port ||= port
|
|
19
|
+
::EventMachine.connect(@hostname, @port, self) do |conn|
|
|
20
|
+
conn.set_comm_inactivity_timeout 60
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.hostname
|
|
25
|
+
@hostname
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.port
|
|
29
|
+
@port
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def initialize *args
|
|
33
|
+
super
|
|
34
|
+
@filecache = Iowa::Caches::LRUCache.new({:maxsize => 10})
|
|
35
|
+
@iowa_client = Iowa::InlineClient.new(nil,nil)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def connection_completed
|
|
39
|
+
@completed = true
|
|
40
|
+
send_data "swiftclient#{Iowa.app.location}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def deliver_file(filename, suffix, params, headers)
|
|
44
|
+
if @filecache.include?(filename)
|
|
45
|
+
d,e,m = @filecache[filename]
|
|
46
|
+
else
|
|
47
|
+
d = File.read(filename)
|
|
48
|
+
e = Digest::SHA256.hexdigest(d)
|
|
49
|
+
m = File.mtime(filename)
|
|
50
|
+
@filecache[filename] = [d,e,m] if d.length < 130000
|
|
51
|
+
end
|
|
52
|
+
if headers.has_key?(CIF_MODIFIED_SINCE) and Time.parse(headers[CIF_MODIFIED_SINCE]) >= m
|
|
53
|
+
send_data "HTTP/1.1 304 Not Modified\r\n\r\n"
|
|
54
|
+
Iowa::Log.info("static #{filename}: 304")
|
|
55
|
+
else
|
|
56
|
+
ct = MIME::Types.type_for("foo.#{suffix}").first
|
|
57
|
+
h = "Connection: close\r\nDate: #{Time.now.httpdate}\r\nLast-Modified: #{m.httpdate}\r\nETag: #{e}\r\nCache-Control: max-age=3600\r\nContent-Type: #{ct ? ct.content_type : 'application/octet-stream'}\r\nContent-Length: #{d.length}\r\n\r\n"
|
|
58
|
+
send_data "HTTP/1.1 200 OK\r\n"
|
|
59
|
+
send_data h
|
|
60
|
+
send_data d
|
|
61
|
+
Iowa::Log.info("static #{filename}: 200")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def handle_file(params,headers)
|
|
66
|
+
path_info = params[CREQUEST_URI]
|
|
67
|
+
qs = params[CQUERY_STRING]
|
|
68
|
+
if path_info == C_slash or path_info == C_empty
|
|
69
|
+
path_info = C_slashindex_html
|
|
70
|
+
elsif path_info =~ /^([^.]+)$/
|
|
71
|
+
path_info = "#{$1}/index.html"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
qsfilename = "#{Iowa.config[Iowa::Capplication][Iowa::Cdoc_root]}#{path_info}__#{qs}"
|
|
75
|
+
filename = "#{Iowa.config[Iowa::Capplication][Iowa::Cdoc_root]}#{path_info}"
|
|
76
|
+
if (FileTest.exist?(filename) and File.expand_path(filename).index(Iowa.config[Iowa::Capplication][Iowa::Cdoc_root]) == 0)
|
|
77
|
+
suffix = path_info.sub(/[_\s]*$/,C_empty)
|
|
78
|
+
deliver_file(filename, File.extname(suffix)[1..-1],params,headers)
|
|
79
|
+
true
|
|
80
|
+
elsif qs and (FileTest.exist?(qsfilename) and File.expand_path(qsfilename).index(Iowa.config[Iowa::Capplication][Iowa::Cdoc_root]) == 0)
|
|
81
|
+
suffix = path_info.sub(/[_\s]*$/,C_empty)
|
|
82
|
+
deliver_file(qsfilename, File.extname(suffix)[1..-1],params,headers)
|
|
83
|
+
true
|
|
84
|
+
else
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def post_init
|
|
90
|
+
@parser = Iowa::HttpParser.new
|
|
91
|
+
@params = {}
|
|
92
|
+
@headers = {}
|
|
93
|
+
@nparsed = 0
|
|
94
|
+
@request = nil
|
|
95
|
+
@request_len = nil
|
|
96
|
+
@linebuffer = ''
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def unbind
|
|
100
|
+
if @completed
|
|
101
|
+
self.class.connect
|
|
102
|
+
else
|
|
103
|
+
Logger['iowa_log'].error "FAILED to connect to cluster server #{self.class.hostname}:#{self.class.port}"
|
|
104
|
+
::EventMachine.add_timer(rand(4)) {self.class.connect}
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def process_http_request(headers,params,buffer)
|
|
109
|
+
unless handle_file(params,headers)
|
|
110
|
+
clen = buffer.length - headers[CCONTENT_LENGTH].to_i
|
|
111
|
+
body = buffer[clen,headers[CCONTENT_LENGTH].to_i]
|
|
112
|
+
request = Iowa::Request::EMHybrid.new(headers,params,body)
|
|
113
|
+
response = Iowa.handleConnection request
|
|
114
|
+
|
|
115
|
+
@iowa_client.reset(request,response)
|
|
116
|
+
send_data "HTTP/1.1 #{response.status_line}\r\n"
|
|
117
|
+
@iowa_client.print(self)
|
|
118
|
+
end
|
|
119
|
+
post_init
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def print(data)
|
|
123
|
+
send_data data
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def receive_data data
|
|
127
|
+
@linebuffer << data
|
|
128
|
+
@nparsed = @parser.execute(@headers, @params, @linebuffer, @nparsed) unless @parser.finished?
|
|
129
|
+
if @parser.finished?
|
|
130
|
+
if @request_len.nil?
|
|
131
|
+
@request_len = @nparsed + @params[CCONTENT_LENGTH].to_i
|
|
132
|
+
if @request_len > MAX_BODY
|
|
133
|
+
new_buffer = Tempfile.new(CEMHYBRIDCLUSTERSERVER)
|
|
134
|
+
new_buffer.binmode
|
|
135
|
+
new_buffer << @linebuffer
|
|
136
|
+
@linebuffer = new_buffer
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
if @linebuffer.length >= @request_len
|
|
141
|
+
process_http_request(@headers,@params,@linebuffer)
|
|
142
|
+
end
|
|
143
|
+
elsif @linebuffer.length > MAX_HEADER
|
|
144
|
+
raise MaxHeaderExceeded
|
|
145
|
+
end
|
|
146
|
+
rescue => e
|
|
147
|
+
Logger['iowa_log'].error "Error while reading request: #{e}"
|
|
148
|
+
close_connection
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
module Iowa
|
|
154
|
+
|
|
155
|
+
# Handle the communications coming in on the monitored socket,
|
|
156
|
+
# create a context object from the data received, and then pass
|
|
157
|
+
# the context information into the Application object for final
|
|
158
|
+
# handling. Exception handling is simply via capturing the Exception
|
|
159
|
+
# and outputting a stack backtrace (this could be improved).
|
|
160
|
+
|
|
161
|
+
class << self
|
|
162
|
+
remove_method(:handleConnection)
|
|
163
|
+
remove_method(:eventLoop)
|
|
164
|
+
remove_method(:run)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def self.handleConnection(request)
|
|
168
|
+
start_time = read_time = Time.now
|
|
169
|
+
mylog = Logger[Ciowa_log]
|
|
170
|
+
|
|
171
|
+
status = []
|
|
172
|
+
response = handleRequest(request)
|
|
173
|
+
begin
|
|
174
|
+
response.status_line = request.status_line if request.status_line
|
|
175
|
+
response.content_type = request.content_type if request.content_type
|
|
176
|
+
status[0] = response.status_line
|
|
177
|
+
if request.headers_out.respond_to?(:length) and request.headers_out.length > 0
|
|
178
|
+
request.headers_out.each {|k,v| response.headers.set(k,v)}
|
|
179
|
+
end
|
|
180
|
+
rescue Exception => e
|
|
181
|
+
mylog.info e.to_s, e.backtrace.inspect
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end_time = Time.now
|
|
185
|
+
logline = "#{start_time} (#{read_time - start_time}/#{end_time - start_time}) :: #{request.uri} \"#{status[0]}\" #{response.body.length}B"
|
|
186
|
+
mylog.info logline
|
|
187
|
+
response
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Outputs the location of the socket being monitored, then enters the
|
|
191
|
+
# event loop to wait for and handle connections.
|
|
192
|
+
|
|
193
|
+
def self.eventLoop
|
|
194
|
+
Logger[Ciowa_log].info 'Entering the EMHybrid event loop...'
|
|
195
|
+
|
|
196
|
+
::EventMachine.run do
|
|
197
|
+
#::EventMachine.start_server @config[Csocket][Chostname], @config[Csocket][Cport], EMHybridClusterServer
|
|
198
|
+
|
|
199
|
+
EMHybridClusterServer.connect(@config[Csocket][Chostname], @config[Csocket][Cport])
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def self.run(*args)
|
|
204
|
+
run_check_started(*args)
|
|
205
|
+
mylog = Logger[Ciowa_log]
|
|
206
|
+
my_ip = @config[Csocket][Chostname]
|
|
207
|
+
my_ip_hex = my_ip.split('.',4).collect {|x| to_hex(x)}.join
|
|
208
|
+
|
|
209
|
+
Iowa.app.location = "#{my_ip_hex}#{sprintf('%04s',$$.to_s(16)).gsub(' ','0')}"
|
|
210
|
+
|
|
211
|
+
app.initialLoad()
|
|
212
|
+
@server = nil
|
|
213
|
+
setup_signal_handlers
|
|
214
|
+
|
|
215
|
+
begin
|
|
216
|
+
eventLoop
|
|
217
|
+
rescue Exception => exception
|
|
218
|
+
mylog.fatal "Catastrophic failure in main event loop: #{exception} :: " + exception.backtrace.join(".....").to_s
|
|
219
|
+
ensure
|
|
220
|
+
File.delete(@config[Csocket][Cpath]) if @config[Csocket].has_key? Cpath
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
data/src/iowa.cgi
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
|
|
5
|
+
This is a simple CGI adaptor that will allow one to use Iowa with any CGI
|
|
6
|
+
capable web server without requiring any special permissions with regard
|
|
7
|
+
to web server configuration.
|
|
8
|
+
|
|
9
|
+
To install the Iowa CGI adaptor:
|
|
10
|
+
- Copy this file into your cgi-bin directory.
|
|
11
|
+
- Set up a url that invokes this script.
|
|
12
|
+
In Apache, this involves adding something like this to your httpd.conf file:
|
|
13
|
+
|
|
14
|
+
Action iowaGuestbook /cgi-bin/iowa_guestbook_adaptor.cgi
|
|
15
|
+
<Location /guestbook>
|
|
16
|
+
SetHandler iowaGuestbook
|
|
17
|
+
</Location>
|
|
18
|
+
|
|
19
|
+
Configuration of the script is simple. Simply replace the text below that
|
|
20
|
+
reads, "[REPLACE_WITH_SOCKET_DEF]" with a valid socket definition
|
|
21
|
+
that points to where your Iowa application is listening.
|
|
22
|
+
|
|
23
|
+
=end
|
|
24
|
+
|
|
25
|
+
require 'iowa/Client'
|
|
26
|
+
|
|
27
|
+
iowa_socket = '[REPLACE_WITH_SOCKET_DEF]'
|
|
28
|
+
client = Iowa::Client.new(iowa_socket)
|
|
29
|
+
client.handle_request
|
data/src/iowa.rb
ADDED
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
rescue Exception
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
require 'yaml'
|
|
7
|
+
#require 'log4r'
|
|
8
|
+
#include Log4r
|
|
9
|
+
|
|
10
|
+
require 'iowa/Constants'
|
|
11
|
+
require 'iowa/Config'
|
|
12
|
+
require 'iowa/Util'
|
|
13
|
+
require 'iowa/String'
|
|
14
|
+
require 'iowa/TemplateParser'
|
|
15
|
+
require 'iowa/Hash'
|
|
16
|
+
require 'iowa/Association'
|
|
17
|
+
require 'iowa/Context'
|
|
18
|
+
require 'iowa/Element'
|
|
19
|
+
require 'iowa/Tag'
|
|
20
|
+
require 'iowa/DynamicElements'
|
|
21
|
+
require 'iowa/Form'
|
|
22
|
+
require 'iowa/Component'
|
|
23
|
+
require 'iowa/DetachedComponent'
|
|
24
|
+
require 'iowa/ComponentProxy'
|
|
25
|
+
require 'iowa/BindingsParser'
|
|
26
|
+
require 'iowa/KeyValueCoding'
|
|
27
|
+
require 'iowa/Session'
|
|
28
|
+
require 'iowa/Application'
|
|
29
|
+
require 'iowa/Request'
|
|
30
|
+
require 'iowa/Response'
|
|
31
|
+
require 'iowa/Email'
|
|
32
|
+
require 'iowa/PrettyException'
|
|
33
|
+
#require 'iowa/request/Apache'
|
|
34
|
+
#require 'iowa/request/FCGI'
|
|
35
|
+
#require 'iowa/request/WEBrick'
|
|
36
|
+
#require 'iowa/request/Mongrel'
|
|
37
|
+
require 'iowa/request/ENV'
|
|
38
|
+
|
|
39
|
+
require 'socket'
|
|
40
|
+
require 'resolv'
|
|
41
|
+
require 'optparse'
|
|
42
|
+
require 'fileutils'
|
|
43
|
+
|
|
44
|
+
module Iowa
|
|
45
|
+
@app = nil
|
|
46
|
+
|
|
47
|
+
def self.started?
|
|
48
|
+
@started ||= nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.started=(val)
|
|
52
|
+
@started = val
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Forks the process. The parent outputs the PID of the child (so that
|
|
56
|
+
# an external invocation process can capture this information) and then
|
|
57
|
+
# exits. The child sets inself as it's session leader and returns.
|
|
58
|
+
|
|
59
|
+
def self.startDaemon(configuration_file,daemonize = nil)
|
|
60
|
+
self.started = true
|
|
61
|
+
Iowa::Application.applicationClass.Config = configuration_file if configuration_file and FileTest.exist?(configuration_file)
|
|
62
|
+
app
|
|
63
|
+
|
|
64
|
+
mylog = Logger[Ciowa_log]
|
|
65
|
+
|
|
66
|
+
daemonize = @config[Capplication][Cdaemonize] if daemonize.nil? and @config[Capplication].has_key?(Cdaemonize)
|
|
67
|
+
daemonize = true if daemonize.nil?
|
|
68
|
+
|
|
69
|
+
if daemonize
|
|
70
|
+
begin
|
|
71
|
+
if (child_pid = fork)
|
|
72
|
+
puts "PID #{child_pid}"
|
|
73
|
+
exit!
|
|
74
|
+
end
|
|
75
|
+
Process.setsid
|
|
76
|
+
|
|
77
|
+
mylog.info "Application started in #{Iowa.runmode} mode; process forked and daemonized as PID #{Process.pid}."
|
|
78
|
+
rescue Exception
|
|
79
|
+
mylog.info "Platform (#{RUBY_PLATFORM}) does not appear to support fork/setsid; skipping"
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
mylog.info "Application started; process not forked."
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.configureExceptionScreens
|
|
87
|
+
@exception_screens = []
|
|
88
|
+
@exception_hosts = []
|
|
89
|
+
if @config.has_key?(Cexceptions)
|
|
90
|
+
if @config[Cexceptions].has_key?(Cscreens)
|
|
91
|
+
@config[Cexceptions][Cscreens].each do |item|
|
|
92
|
+
new_item = {}
|
|
93
|
+
next unless item.is_a?(::Hash)
|
|
94
|
+
item.each do |k,v|
|
|
95
|
+
k.sub!(/^\s+/,'')
|
|
96
|
+
v.sub!(/^\s+/,'')
|
|
97
|
+
c,m = v.split('.',2)
|
|
98
|
+
dd = Iowa::DispatchDestination.new(c,m)
|
|
99
|
+
if m = /^\/(.*)\//.match(k)
|
|
100
|
+
new_item[Regexp.new(m[1]),true] = dd
|
|
101
|
+
else
|
|
102
|
+
new_item[k] = dd
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
@exception_screens.push(new_item)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
if @config[Cexceptions].has_key?(Chosts)
|
|
109
|
+
@config[Cexceptions][Chosts].each do |item|
|
|
110
|
+
new_item = {}
|
|
111
|
+
next unless item.is_a?(::Hash)
|
|
112
|
+
item.each do |k,v|
|
|
113
|
+
k.sub!(/^\s+/,'')
|
|
114
|
+
if v.is_a?(Array)
|
|
115
|
+
list = []
|
|
116
|
+
v.each {|x| list.push(Regexp.new(x.sub(/^\s+/,''),true))}
|
|
117
|
+
new_item[k] = list
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
@exception_hosts.push(new_item)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# configuration, and set the defaults for information that was
|
|
127
|
+
# omitted. Exceptions will be raised if socket information is
|
|
128
|
+
# missing, or if either socket or logging information seems to
|
|
129
|
+
# have errors.
|
|
130
|
+
|
|
131
|
+
def self.checkConfiguration
|
|
132
|
+
cc_setup
|
|
133
|
+
cc_socket
|
|
134
|
+
cc_logging
|
|
135
|
+
cc_misc
|
|
136
|
+
|
|
137
|
+
configureExceptionScreens
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
private
|
|
141
|
+
def self.cc_setup
|
|
142
|
+
# Make sure socket info was provided
|
|
143
|
+
@config[Csocket][Cport] = 2001 if (!@config[Csocket].has_key?(Cport) and !@config[Csocket].has_key?(Cpath))
|
|
144
|
+
@config[Csocket][Chostname] = '127.0.0.1' if (!@config[Csocket].has_key?(Chostname) and !@config[Csocket].has_key?(Cpath))
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def self.cc_misc
|
|
148
|
+
@config[Capplication][Cdaemonize] = false unless @config[Capplication].has_key?(Cdaemonize)
|
|
149
|
+
@config[Capplication][Cdoc_root] = File.expand_path(@config[Capplication][Cdoc_root]) if @config[Capplication].has_key?(Cdoc_root)
|
|
150
|
+
@config[Capplication][Ccgi_root] = File.expand_path(@config[Capplication][Ccgi_root]) if @config[Capplication].has_key?(Ccgi_root)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.cc_logging
|
|
154
|
+
unless @config.has_key?(Clogger)
|
|
155
|
+
if @config.has_key?(Clogging)
|
|
156
|
+
@config[Clogger] = @config[Clogging]
|
|
157
|
+
@config[Clogger][Cclass] = 'Log4rLogger' unless @config[Clogger].has_key?(Cclass)
|
|
158
|
+
else
|
|
159
|
+
@config[Clogger][Cclass] = 'Logger'
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
@config[Clogger][Cbasedir] = @config[Capplication][Clog_root] || '.' unless @config[Clogger].has_key?(Cbasedir)
|
|
163
|
+
@config[Clogger][Cfilename] = 'iowa_log' unless @config[Clogger].has_key?(Cfilename)
|
|
164
|
+
@config[Clogger][Cmaxage] = :daily unless @config[Clogger].has_key?(Cmaxage)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def self.cc_socket_errors
|
|
168
|
+
raise "Please define only one of a TCP or a Unix domain socket in the configuration file." if @config[Csocket].has_key?(Cpath) and @config[Csocket].has_key?(Cport)
|
|
169
|
+
raise "The socket hostname contains illegal characters." unless @config[Csocket].has_key?(Chostname) and @config[Csocket][Chostname] =~ /^[a-zA-Z0-9\.\-]*$/
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def self.cc_socket_resolveable
|
|
173
|
+
if @config[Csocket].has_key?(Chostname) and @config[Csocket][Chostname] !~ /^\s*\d+\.\d+\.\d+\.\d+\s*$/
|
|
174
|
+
begin
|
|
175
|
+
@config[Csocket][Chostname] = Resolv::getaddress(@config[Csocket][Chostname])
|
|
176
|
+
rescue Resolv::ResolvError
|
|
177
|
+
raise "The socket hostname must be resolveable to an IP address."
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def self.cc_socket_valid_path
|
|
183
|
+
if @config[Csocket].has_key? Cpath
|
|
184
|
+
begin
|
|
185
|
+
File.unlink @config[Csocket][Cpath] if FileTest.exist? @config[Csocket][Cpath]
|
|
186
|
+
sf = File.open(@config[Csocket][Cpath],'w')
|
|
187
|
+
@config[Csocket][Cbasename] = File.basename(@config[Csocket][Cpath])
|
|
188
|
+
sf.close
|
|
189
|
+
File.unlink @config[Csocket][Cpath]
|
|
190
|
+
rescue Exception => exception
|
|
191
|
+
puts "The path for a Unix socket must be writeable."
|
|
192
|
+
raise
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def self.cc_socket
|
|
198
|
+
cc_socket_errors
|
|
199
|
+
cc_socket_resolveable
|
|
200
|
+
cc_socket_valid_path
|
|
201
|
+
end
|
|
202
|
+
public
|
|
203
|
+
# Initialize logging mechanisms
|
|
204
|
+
|
|
205
|
+
def self.startLogging
|
|
206
|
+
lcfg = @config[Clogging]
|
|
207
|
+
mylog = Logger.new Ciowa_log
|
|
208
|
+
myformat = PatternFormatter.new :pattern => '[%l] %C @ %d :: %M'
|
|
209
|
+
mybaselog = RollingFileOutputter.new Cbaselog, :maxsize => lcfg[Cmaxsize], :maxtime => lcfg[Cmaxage], :level => lcfg[Cminlevel], :filename => lcfg[Cfilename], :trunc => false, :formatter => myformat
|
|
210
|
+
mylog.outputters = mybaselog
|
|
211
|
+
|
|
212
|
+
mylog.info 'Logging subsystem initialized.'
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def self.maybe_kind_of(obj,classname)
|
|
216
|
+
r = false
|
|
217
|
+
obj.class.ancestors.each {|a| r ||= a.to_s == classname}
|
|
218
|
+
r
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Check the exception against the list of exception screens, if any. Return as
|
|
222
|
+
# soon as a match is found.
|
|
223
|
+
|
|
224
|
+
def self.checkScreen(exception)
|
|
225
|
+
klass = exception.class.to_s
|
|
226
|
+
@exception_screens.each do |item|
|
|
227
|
+
item.each do |k,v|
|
|
228
|
+
if k.is_a?(Regexp)
|
|
229
|
+
if k.match(klass)
|
|
230
|
+
return v
|
|
231
|
+
end
|
|
232
|
+
elsif maybe_kind_of(exception,k)
|
|
233
|
+
return v
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
nil
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def self.internal_host?(request)
|
|
241
|
+
addr = false
|
|
242
|
+
browser = false
|
|
243
|
+
@exception_hosts.each do |host|
|
|
244
|
+
if host.has_key?(Caddresses)
|
|
245
|
+
host[Caddresses].each do |a|
|
|
246
|
+
if a.match(request.remote_host)
|
|
247
|
+
addr = true
|
|
248
|
+
break
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
elsif host.has_key?(Cips)
|
|
252
|
+
host[Cips].each do |i|
|
|
253
|
+
if i.match(request.remote_addr)
|
|
254
|
+
addr = true
|
|
255
|
+
break
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
else
|
|
259
|
+
addr = true
|
|
260
|
+
end
|
|
261
|
+
if host.has_key?(Cbrowsers)
|
|
262
|
+
host[Cbrowsers].each do |b|
|
|
263
|
+
if b.match(request.headers_in[CUserAgent])
|
|
264
|
+
browser = true
|
|
265
|
+
break
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
else
|
|
269
|
+
browser = true
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
(addr and browser)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def self.handleRequest(request)
|
|
276
|
+
mylog = Logger[Ciowa_log]
|
|
277
|
+
deployed_screen = false
|
|
278
|
+
dispatch_destination = nil
|
|
279
|
+
response = Iowa::Response.new(200)
|
|
280
|
+
original_exception = nil
|
|
281
|
+
context = nil
|
|
282
|
+
loop do
|
|
283
|
+
begin
|
|
284
|
+
response.content_type = Ctext_html
|
|
285
|
+
exception = nil
|
|
286
|
+
exception = catch(:session_error) do
|
|
287
|
+
begin
|
|
288
|
+
context = Iowa::Context.new(request, response)
|
|
289
|
+
context.prior_exception = original_exception if original_exception
|
|
290
|
+
app.handleRequest(context,dispatch_destination)
|
|
291
|
+
rescue Exception => exception
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
if exception.to_s != C_empty and exception.kind_of?(Exception)
|
|
295
|
+
mylog = Logger[Ciowa_log]
|
|
296
|
+
mylog.warn "Execution Error: #{exception} :: " + exception.backtrace.join(".....").to_s unless original_exception
|
|
297
|
+
if internal_host?(request)
|
|
298
|
+
mylog.info "Showing PrettyException"
|
|
299
|
+
response << Iowa::PrettyException.new(exception).to_s
|
|
300
|
+
else
|
|
301
|
+
if deployed_screen == false and dispatch_destination = checkScreen(exception)
|
|
302
|
+
dd = dispatch_destination.method ? "#{dispatch_destination.component}.#{dispatch_destination.method}" :
|
|
303
|
+
dispatch_destination.component
|
|
304
|
+
mylog.info "Deploying exception screen #{dd}"
|
|
305
|
+
response.status = Iowa::Response::InternalServerError
|
|
306
|
+
original_exception = exception
|
|
307
|
+
deployed_screen = true
|
|
308
|
+
raise "retry"
|
|
309
|
+
else
|
|
310
|
+
response.status = Iowa::Response::InternalServerError unless response.status >= 400
|
|
311
|
+
mylog.info "Showing ugly exception"
|
|
312
|
+
exception = original_exception if original_exception
|
|
313
|
+
response << "<p> An unhandled error has occured. Please inform your system or site's administrator of the error.</p>" if response.status == Iowa::Response::InternalServerError
|
|
314
|
+
response << "<p>#{exception.to_s.gsub("<","<")}<br/>"
|
|
315
|
+
response << "</p>"
|
|
316
|
+
status = 'EOUT'
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
rescue
|
|
321
|
+
retry
|
|
322
|
+
end
|
|
323
|
+
break
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
# Unless the app forbids it or this is a page that went into the page cache,
|
|
327
|
+
# at this point we will write a cache of the generated page to the filesystem.
|
|
328
|
+
# This will allow pages that only need to be generated occasionally to be
|
|
329
|
+
# served as static content most of the time. Whether this is turned on or not
|
|
330
|
+
# is controlled by an application level config option, docroot_caching. It is
|
|
331
|
+
# turned off by default.
|
|
332
|
+
if context[:skip_pagecache] and context[:allow_docroot_caching]
|
|
333
|
+
if Iowa.config[Capplication][Cdocroot_caching]
|
|
334
|
+
if context.request.params['QUERY_STRING'].to_s != ''
|
|
335
|
+
path = "#{File.expand_path(File.join(Iowa.config[Capplication][Cdoc_root],context.request.uri))}__#{context.request.params['QUERY_STRING']}"
|
|
336
|
+
else
|
|
337
|
+
path = "#{File.expand_path(File.join(Iowa.config[Capplication][Cdoc_root],context.request.uri))}"
|
|
338
|
+
end
|
|
339
|
+
# Make sure that the path is inside the docroot!
|
|
340
|
+
if (path.index(Iowa.config[Capplication][Cdoc_root]) == 0)
|
|
341
|
+
begin
|
|
342
|
+
mylog.info "Writing cache entry: #{path}"
|
|
343
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
344
|
+
File.open(path,'w+') {|fh| fh.write response.body}
|
|
345
|
+
rescue Exception => e
|
|
346
|
+
# Well, that's too bad. Report the error and go on.
|
|
347
|
+
mylog.error "Error while writing filesystem cached page: #{e}"
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
if context.session
|
|
353
|
+
context.session.context = nil
|
|
354
|
+
context.session = nil
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
response
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Handle the communications coming in on the monitored socket,
|
|
361
|
+
# create a context object from the data received, and then pass
|
|
362
|
+
# the context information into the Application object for final
|
|
363
|
+
# handling. Exception handling is simply via capturing the Exception
|
|
364
|
+
# and outputting a stack backtrace (this could be improved).
|
|
365
|
+
|
|
366
|
+
def self.handleConnection(socket)
|
|
367
|
+
begin
|
|
368
|
+
Thread.current.priority = 2
|
|
369
|
+
start_time = Time.now
|
|
370
|
+
mylog = Logger[Ciowa_log]
|
|
371
|
+
message = ''
|
|
372
|
+
while (recv = socket.recv(8192)) != C_empty
|
|
373
|
+
message << recv
|
|
374
|
+
end
|
|
375
|
+
socket.shutdown(0)
|
|
376
|
+
read_time = Time.now
|
|
377
|
+
status = [COK]
|
|
378
|
+
rescue Exception => exception
|
|
379
|
+
mylog.error "Failure While Reading Inbound Data: #{exception}"
|
|
380
|
+
# TODO: When this happens, we need to either create a Request and return a useful response, or close the socket.
|
|
381
|
+
status = [CEIN, "Failure While Reading Inbound Data: #{exception}"]
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
begin
|
|
385
|
+
request = Marshal.load(message)
|
|
386
|
+
unless request.headers and request.headers.length > 0
|
|
387
|
+
request.headers = request.headers_in if request.headers_in.respond_to?(:length) and request.headers_in.length > 0
|
|
388
|
+
end
|
|
389
|
+
# Backward compatible yuckiness.
|
|
390
|
+
#request.content_type = nil
|
|
391
|
+
#request.status_line = nil
|
|
392
|
+
#request.headers_out = {}
|
|
393
|
+
rescue Exception => exception
|
|
394
|
+
mylog.error "Inbound Data Corruption: #{exception}"
|
|
395
|
+
status = [CEIN,"Inbound Data Corruption: #{exception}"]
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
unless status[0] == CEIN
|
|
399
|
+
response = handleRequest(request)
|
|
400
|
+
# Backward compatible yuckiness, continued.
|
|
401
|
+
response.status_line = request.status_line if request.status_line
|
|
402
|
+
response.content_type = request.content_type if request.content_type
|
|
403
|
+
status[0] = response.status_line
|
|
404
|
+
if request.headers_out.respond_to?(:length) and request.headers_out.length > 0
|
|
405
|
+
request.headers_out.each {|k,v| response.headers.set(k,v)}
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
begin
|
|
409
|
+
message = Marshal.dump(response)
|
|
410
|
+
socket.write(message)
|
|
411
|
+
socket.flush
|
|
412
|
+
socket.shutdown(1)
|
|
413
|
+
end_time = Time.now
|
|
414
|
+
rescue Exception => exception
|
|
415
|
+
mylog.error "Failure While Writing Outbound Data: #{exception}"
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
logline = "#{start_time} (#{read_time.to_f - start_time.to_f}/#{end_time.to_f - start_time.to_f}) :: #{request.uri} \"#{status[0]}\" #{response.body.length}B"
|
|
419
|
+
#mylog.info logline
|
|
420
|
+
else
|
|
421
|
+
response = Iowa::Response.new(500)
|
|
422
|
+
response.body = "BOOM: #{status[1]}"
|
|
423
|
+
message = Marshal.dump(response)
|
|
424
|
+
socket.write(message)
|
|
425
|
+
socket.flush
|
|
426
|
+
socket.shutdown(1)
|
|
427
|
+
logline = "#{start_time} (#{read_time.to_f - start_time.to_f}/#{end_time.to_f - start_time.to_f}) :: #{request.uri} ERROR #{response.body.length}B"
|
|
428
|
+
mylog.info logline
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
# Outputs the location of the socket being monitored, then enters the
|
|
433
|
+
# event loop to wait for and handle connections.
|
|
434
|
+
|
|
435
|
+
def self.eventLoop(server)
|
|
436
|
+
Logger[Ciowa_log].info 'Entering the main event loop...'
|
|
437
|
+
loop do
|
|
438
|
+
socket = server.accept
|
|
439
|
+
Thread.start do
|
|
440
|
+
Thread.current[:worker] = true
|
|
441
|
+
handleConnection socket
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# Outputs the location of the socket being monitored, then enters the
|
|
447
|
+
# event loop to wait for and handle connections.
|
|
448
|
+
|
|
449
|
+
def self.to_hex(n)
|
|
450
|
+
sprintf('%02s',n.to_i.to_s(16)).sub(' ','0')
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
def self.run_check_started(*args)
|
|
454
|
+
unless started?
|
|
455
|
+
# Not started yet; call startDaemon()
|
|
456
|
+
if args[0].is_a?(::Hash)
|
|
457
|
+
# Pretty argument passing
|
|
458
|
+
ah = args.shift
|
|
459
|
+
daemonize = ah[:daemonize] ? true : false
|
|
460
|
+
path = ah[:config] ? ah[:config] : args[0] ? args.shift.to_s : nil
|
|
461
|
+
path = File.join( Iowa::Application.root_directory,
|
|
462
|
+
File.basename($0).sub( /\.\w+$/, '.cnf' ) ) unless path
|
|
463
|
+
else
|
|
464
|
+
daemonize = (args[0].is_a?(TrueClass) or args[0].is_a?(FalseClass)) ? args.shift : nil
|
|
465
|
+
path = args[0] ? args.shift.to_s : nil
|
|
466
|
+
path = File.join( Iowa::Application.root_directory,
|
|
467
|
+
File.basename($0).sub( /\.\w+$/, '.cnf' ) ) unless path
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
startDaemon(path,daemonize)
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
def self.run(*args)
|
|
475
|
+
run_check_started(*args)
|
|
476
|
+
mylog = Logger[Ciowa_log]
|
|
477
|
+
my_ip = @config[Csocket][Chostname]
|
|
478
|
+
my_ip_hex = my_ip.split('.',4).collect {|x| to_hex(x)}.join
|
|
479
|
+
|
|
480
|
+
if @config[Csocket].has_key? Cport
|
|
481
|
+
socket_host = @config[Csocket][Chostname]
|
|
482
|
+
socket_port = @config[Csocket][Cport]
|
|
483
|
+
my_port_hex = sprintf('%04s',socket_port.to_i.to_s(16)).gsub(' ','0')
|
|
484
|
+
begin
|
|
485
|
+
# This should be configurable and runtime toggleable.
|
|
486
|
+
TCPServer.do_not_reverse_lookup = true
|
|
487
|
+
if socket_host.to_s == ''
|
|
488
|
+
@server = TCPServer.new(socket_port)
|
|
489
|
+
mylog.info "Listening at localhost:#{socket_port}."
|
|
490
|
+
else
|
|
491
|
+
@server = TCPServer.new(socket_host,socket_port)
|
|
492
|
+
mylog.info "Listening at #{socket_host}:#{socket_port}."
|
|
493
|
+
end
|
|
494
|
+
app.location = "#{my_ip_hex}#{my_port_hex}"
|
|
495
|
+
rescue Exception => exception
|
|
496
|
+
mylog.fatal "Failure while attempting to establish a TCP socket at #{socket_host}:#{socket_port} : #{exception}"
|
|
497
|
+
raise
|
|
498
|
+
end
|
|
499
|
+
else
|
|
500
|
+
begin
|
|
501
|
+
@server = UNIXServer.new(@config[Csocket][Cpath])
|
|
502
|
+
File.chmod(0666, @config[Csocket][Cpath])
|
|
503
|
+
mylog.info "Listening on #{@config[Csocket][Cpath]}."
|
|
504
|
+
rescue Exception => exception
|
|
505
|
+
mylog.fatal "Failure while attemting to establish a Unix socket at #{@config[Csocket][Cpath]} : #{exception}"
|
|
506
|
+
raise
|
|
507
|
+
end
|
|
508
|
+
if app.serial_number.to_s != ''
|
|
509
|
+
app.location = "00000000#{sprintf('%04s',Iowa.app.serial_number.to_i.to_s(16)).gsub(' ','0')}"
|
|
510
|
+
else
|
|
511
|
+
app.location = ''
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
app.initialLoad()
|
|
516
|
+
setup_signal_handlers
|
|
517
|
+
|
|
518
|
+
begin
|
|
519
|
+
eventLoop(@server)
|
|
520
|
+
rescue Exception => exception
|
|
521
|
+
mylog.fatal "Catastrophic failure in main event loop: #{exception} :: " + exception.backtrace.join(".....").to_s
|
|
522
|
+
ensure
|
|
523
|
+
@server.close if @server
|
|
524
|
+
File.delete(@config[Csocket][Cpath]) if @config[Csocket].has_key? Cpath
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def Iowa.app
|
|
529
|
+
if @app
|
|
530
|
+
@app
|
|
531
|
+
else
|
|
532
|
+
@app = Application.newApplication(Application.root_directory)
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
def Iowa.config
|
|
537
|
+
@config
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def self.setup_signal_handlers
|
|
541
|
+
# A clean shutdown will wait up to a minute for any existing worker threads
|
|
542
|
+
# to finish before shutting down.
|
|
543
|
+
Logger['iowa_log'].info "Setting up signal handlers."
|
|
544
|
+
|
|
545
|
+
trap("INT") {Iowa.clean_shutdown}
|
|
546
|
+
trap("TERM") {Iowa.clean_shutdown}
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
def self.clean_shutdown
|
|
550
|
+
# If, for whatever reason, this is taking too long, a second signal will
|
|
551
|
+
# cause it to shut down immediately.
|
|
552
|
+
|
|
553
|
+
# A dirty shutdown doesn't wait for anything to finish.
|
|
554
|
+
|
|
555
|
+
trap("INT") { Iowa.dirty_shutdown }
|
|
556
|
+
trap("TERM") { Iowa.dirty_shutdown }
|
|
557
|
+
Logger['iowa_log'].info "Shutting down."
|
|
558
|
+
|
|
559
|
+
@server.close if @server and @server.respond_to?(:close)
|
|
560
|
+
threads_running = true
|
|
561
|
+
count = 0
|
|
562
|
+
while threads_running
|
|
563
|
+
# Don't wait forever....
|
|
564
|
+
count += 1
|
|
565
|
+
break if count > 30
|
|
566
|
+
threads_running = false
|
|
567
|
+
Thread.list.each {|t| threads_running = true if t[:worker] and t.alive?}
|
|
568
|
+
Logger['iowa_log'].info " ...still waiting for #{thread_count} threads." if threads_running
|
|
569
|
+
sleep 2 if threads_running
|
|
570
|
+
end
|
|
571
|
+
File.delete(@config[Csocket][Cpath]) if @config[Csocket].has_key? Cpath
|
|
572
|
+
ensure
|
|
573
|
+
Logger['iowa_log'].info "Clean shutdown."
|
|
574
|
+
Iowa::Log.close
|
|
575
|
+
::Process.exit!
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
def self.thread_count
|
|
579
|
+
r = 0
|
|
580
|
+
Thread.list.each {|t| r += 1 if t[:worker] and t.alive?}
|
|
581
|
+
r
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
def self.dirty_shutdown
|
|
585
|
+
@server.close unless !@server or !server.respond_to(:close) or (@server and @server.closed?)
|
|
586
|
+
File.delete(@config[Csocket][Cpath]) if @config[Csocket].has_key? Cpath
|
|
587
|
+
ensure
|
|
588
|
+
Logger['iowa_log'].info "Dirty shutdown."
|
|
589
|
+
Iowa::Log.close
|
|
590
|
+
::Process.exit!
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
def self.runmode
|
|
594
|
+
@runmode
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
def self.runmode=(mode)
|
|
598
|
+
@runmode = mode
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
OptionParser.new do |opts|
|
|
604
|
+
opts.banner = 'Usage: scriptname.rb [options]'
|
|
605
|
+
opts.separator ''
|
|
606
|
+
opts.on('-r','--run [MODE]', [:marshal, :webrick, :mongrel, :httpmachine, :hybrid, :hybridcluster],
|
|
607
|
+
"Select run mode (marshal, webrick, mongrel, httpmachine, hybrid); defaults to standalone") do |m|
|
|
608
|
+
case m
|
|
609
|
+
when :webrick
|
|
610
|
+
require 'iowa_webrick'
|
|
611
|
+
when :mongrel
|
|
612
|
+
require 'iowa_mongrel'
|
|
613
|
+
when :httpmachine
|
|
614
|
+
require 'iowa_httpmachine'
|
|
615
|
+
when :hybrid
|
|
616
|
+
require 'iowa_hybrid'
|
|
617
|
+
when :hybridcluster
|
|
618
|
+
require 'iowa_hybrid_cluster'
|
|
619
|
+
when :marshal
|
|
620
|
+
Iowa.runmode = :marshal
|
|
621
|
+
else
|
|
622
|
+
require 'webrick'
|
|
623
|
+
Iowa.runmode = :webrick
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
opts.on('-p','--port [NUMBER]',Integer,"Port to run IOWA process on") do |m|
|
|
627
|
+
Iowa.config[::Iowa::Csocket][::Iowa::Cport] = m
|
|
628
|
+
end
|
|
629
|
+
opts.on('-h','--host [HOST]',String,"Hostname or IP address to bind to") do |m|
|
|
630
|
+
Iowa.config[::Iowa::Csocket][::Iowa::Chost] = m
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
end.parse!
|
|
634
|
+
|
|
635
|
+
unless Iowa.runmode
|
|
636
|
+
require 'iowa_webrick'
|
|
637
|
+
end
|