passenger 3.0.21 → 3.9.1.beta
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data/DEVELOPERS.TXT +4 -10
- data/NEWS +19 -27
- data/Rakefile +20 -19
- data/bin/passenger +3 -2
- data/bin/passenger-config +35 -5
- data/bin/passenger-install-apache2-module +12 -12
- data/bin/passenger-install-nginx-module +55 -38
- data/bin/passenger-memory-stats +3 -1
- data/bin/passenger-status +7 -35
- data/build/agents.rb +107 -21
- data/build/apache2.rb +11 -46
- data/build/basics.rb +61 -9
- data/build/common_library.rb +59 -142
- data/build/cxx_tests.rb +111 -110
- data/build/documentation.rb +33 -0
- data/build/misc.rb +30 -12
- data/build/nginx.rb +10 -39
- data/build/oxt_tests.rb +1 -0
- data/build/ruby_extension.rb +1 -5
- data/build/test_basics.rb +3 -2
- data/dev/copy_boost_headers.rb +2 -1
- data/doc/Architectural overview.html +49 -90
- data/doc/DebuggingAndStressTesting.txt.md +49 -0
- data/doc/Packaging.txt.md +254 -0
- data/doc/Security of user switching support.html +35 -66
- data/doc/Users guide Apache.html +588 -758
- data/doc/Users guide Apache.idmap.txt +253 -136
- data/doc/Users guide Apache.txt +154 -109
- data/doc/Users guide Nginx.html +544 -660
- data/doc/Users guide Nginx.idmap.txt +179 -91
- data/doc/Users guide Nginx.txt +192 -118
- data/doc/Users guide Standalone.html +65 -48
- data/doc/Users guide Standalone.idmap.txt +10 -2
- data/doc/Users guide Standalone.txt +4 -0
- data/doc/images/glyphicons-halflings-white.png +0 -0
- data/doc/images/glyphicons-halflings.png +0 -0
- data/doc/images/phusion_banner_small.png +0 -0
- data/doc/images/{smart-lv2.png → smart.png} +0 -0
- data/doc/images/{smart-lv2.svg → smart.svg} +0 -0
- data/doc/templates/bootstrap.min.css +397 -0
- data/doc/templates/markdown.html.erb +117 -0
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +2 -1
- data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +26 -48
- data/doc/users_guide_snippets/passenger_spawn_method.txt +18 -30
- data/doc/users_guide_snippets/support_information.txt +30 -0
- data/ext/apache2/Bucket.cpp +9 -26
- data/ext/apache2/Bucket.h +13 -10
- data/ext/apache2/Configuration.cpp +70 -58
- data/ext/apache2/Configuration.hpp +19 -47
- data/ext/apache2/DirectoryMapper.h +7 -7
- data/ext/apache2/Hooks.cpp +150 -313
- data/ext/boost/algorithm/string/detail/case_conv.hpp +4 -2
- data/ext/boost/algorithm/string/detail/find_format.hpp +20 -20
- data/ext/boost/algorithm/string/detail/find_format_all.hpp +23 -23
- data/ext/boost/algorithm/string/detail/find_format_store.hpp +2 -2
- data/ext/boost/algorithm/string/detail/formatter.hpp +25 -0
- data/ext/boost/algorithm/string/formatter.hpp +20 -3
- data/ext/boost/assert.hpp +85 -4
- data/ext/boost/bind/bind.hpp +1 -1
- data/ext/boost/concept/detail/backward_compatibility.hpp +1 -1
- data/ext/boost/concept_check.hpp +140 -64
- data/ext/boost/config.hpp +1 -1
- data/ext/boost/config/auto_link.hpp +8 -6
- data/ext/boost/config/compiler/borland.hpp +12 -2
- data/ext/boost/config/compiler/clang.hpp +89 -30
- data/ext/boost/config/compiler/codegear.hpp +3 -2
- data/ext/boost/config/compiler/common_edg.hpp +7 -5
- data/ext/boost/config/compiler/cray.hpp +61 -0
- data/ext/boost/config/compiler/digitalmars.hpp +9 -1
- data/ext/boost/config/compiler/gcc.hpp +33 -24
- data/ext/boost/config/compiler/gcc_xml.hpp +4 -0
- data/ext/boost/config/compiler/hp_acc.hpp +12 -1
- data/ext/boost/config/compiler/intel.hpp +78 -4
- data/ext/boost/config/compiler/metrowerks.hpp +4 -1
- data/ext/boost/config/compiler/mpw.hpp +4 -1
- data/ext/boost/config/compiler/nvcc.hpp +8 -66
- data/ext/boost/config/compiler/pathscale.hpp +80 -0
- data/ext/boost/config/compiler/pgi.hpp +5 -5
- data/ext/boost/config/compiler/sunpro_cc.hpp +4 -1
- data/ext/boost/config/compiler/vacpp.hpp +37 -13
- data/ext/boost/config/compiler/visualc.hpp +24 -11
- data/ext/boost/config/platform/bsd.hpp +1 -1
- data/ext/boost/config/platform/cray.hpp +18 -0
- data/ext/boost/config/platform/cygwin.hpp +10 -0
- data/ext/boost/config/platform/linux.hpp +5 -0
- data/ext/boost/config/platform/macos.hpp +5 -4
- data/ext/boost/config/platform/symbian.hpp +5 -2
- data/ext/boost/config/platform/vms.hpp +25 -0
- data/ext/boost/config/platform/win32.hpp +7 -1
- data/ext/boost/config/select_compiler_config.hpp +8 -25
- data/ext/boost/config/select_platform_config.hpp +8 -1
- data/ext/boost/config/select_stdlib_config.hpp +9 -1
- data/ext/boost/config/stdlib/dinkumware.hpp +6 -9
- data/ext/boost/config/stdlib/libcomo.hpp +1 -4
- data/ext/boost/config/stdlib/libcpp.hpp +36 -0
- data/ext/boost/config/stdlib/libstdcpp3.hpp +37 -11
- data/ext/boost/config/stdlib/modena.hpp +1 -4
- data/ext/boost/config/stdlib/msl.hpp +1 -4
- data/ext/boost/config/stdlib/roguewave.hpp +9 -6
- data/ext/boost/config/stdlib/sgi.hpp +12 -4
- data/ext/boost/config/stdlib/stlport.hpp +11 -4
- data/ext/boost/config/stdlib/vacpp.hpp +11 -4
- data/ext/boost/config/suffix.hpp +71 -6
- data/ext/boost/config/warning_disable.hpp +1 -1
- data/ext/boost/container/container_fwd.hpp +177 -0
- data/ext/boost/cstdint.hpp +17 -12
- data/ext/boost/current_function.hpp +2 -1
- data/ext/boost/date_time/c_time.hpp +17 -1
- data/ext/boost/date_time/compiler_config.hpp +13 -15
- data/ext/boost/date_time/date_formatting.hpp +7 -1
- data/ext/boost/date_time/filetime_functions.hpp +4 -4
- data/ext/boost/date_time/gregorian_calendar.ipp +2 -2
- data/ext/boost/date_time/strings_from_facet.hpp +3 -3
- data/ext/boost/date_time/time_facet.hpp +101 -101
- data/ext/boost/detail/endian.hpp +4 -2
- data/ext/boost/detail/fenv.hpp +74 -0
- data/ext/boost/detail/sp_typeinfo.hpp +6 -0
- data/ext/boost/exception/detail/clone_current_exception.hpp +47 -0
- data/ext/boost/exception/detail/exception_ptr.hpp +194 -122
- data/ext/boost/exception/detail/type_info.hpp +3 -3
- data/ext/boost/exception/diagnostic_information.hpp +37 -21
- data/ext/boost/exception/exception.hpp +21 -1
- data/ext/boost/exception/info.hpp +0 -1
- data/ext/boost/function.hpp +2 -2
- data/ext/boost/function/function_base.hpp +15 -9
- data/ext/boost/function/function_template.hpp +26 -48
- data/ext/boost/integer_fwd.hpp +0 -16
- data/ext/boost/integer_traits.hpp +2 -2
- data/ext/boost/iterator.hpp +1 -1
- data/ext/boost/iterator/iterator_adaptor.hpp +1 -7
- data/ext/boost/iterator/iterator_facade.hpp +13 -13
- data/ext/boost/iterator/transform_iterator.hpp +5 -20
- data/ext/boost/lexical_cast.hpp +1655 -673
- data/ext/boost/math/policies/policy.hpp +982 -0
- data/ext/boost/math/special_functions/detail/fp_traits.hpp +570 -0
- data/ext/boost/math/special_functions/detail/round_fwd.hpp +80 -0
- data/ext/boost/math/special_functions/fpclassify.hpp +533 -0
- data/ext/boost/math/special_functions/math_fwd.hpp +1070 -0
- data/ext/boost/math/special_functions/sign.hpp +145 -0
- data/ext/boost/math/tools/config.hpp +321 -0
- data/ext/boost/math/tools/promotion.hpp +150 -0
- data/ext/boost/math/tools/real_cast.hpp +29 -0
- data/ext/boost/math/tools/user.hpp +97 -0
- data/ext/boost/move/move.hpp +1222 -0
- data/ext/boost/mpl/O1_size.hpp +40 -0
- data/ext/boost/mpl/O1_size_fwd.hpp +24 -0
- data/ext/boost/mpl/advance.hpp +76 -0
- data/ext/boost/mpl/advance_fwd.hpp +28 -0
- data/ext/boost/mpl/at.hpp +52 -0
- data/ext/boost/mpl/at_fwd.hpp +24 -0
- data/ext/boost/mpl/aux_/O1_size_impl.hpp +87 -0
- data/ext/boost/mpl/aux_/advance_backward.hpp +128 -0
- data/ext/boost/mpl/aux_/advance_forward.hpp +127 -0
- data/ext/boost/mpl/aux_/arithmetic_op.hpp +92 -0
- data/ext/boost/mpl/aux_/at_impl.hpp +45 -0
- data/ext/boost/mpl/aux_/begin_end_impl.hpp +101 -0
- data/ext/boost/mpl/aux_/clear_impl.hpp +35 -0
- data/ext/boost/mpl/aux_/comparison_op.hpp +83 -0
- data/ext/boost/mpl/aux_/config/forwarding.hpp +27 -0
- data/ext/boost/mpl/aux_/config/typeof.hpp +38 -0
- data/ext/boost/mpl/aux_/contains_impl.hpp +61 -0
- data/ext/boost/mpl/aux_/find_if_pred.hpp +31 -0
- data/ext/boost/mpl/aux_/fold_impl.hpp +43 -0
- data/ext/boost/mpl/aux_/has_begin.hpp +23 -0
- data/ext/boost/mpl/aux_/has_size.hpp +23 -0
- data/ext/boost/mpl/aux_/has_tag.hpp +23 -0
- data/ext/boost/mpl/aux_/inserter_algorithm.hpp +159 -0
- data/ext/boost/mpl/aux_/is_msvc_eti_arg.hpp +64 -0
- data/ext/boost/mpl/aux_/iter_apply.hpp +47 -0
- data/ext/boost/mpl/aux_/iter_fold_if_impl.hpp +210 -0
- data/ext/boost/mpl/aux_/iter_fold_impl.hpp +42 -0
- data/ext/boost/mpl/aux_/lambda_spec.hpp +49 -0
- data/ext/boost/mpl/aux_/largest_int.hpp +63 -0
- data/ext/boost/mpl/aux_/msvc_eti_base.hpp +77 -0
- data/ext/boost/mpl/aux_/msvc_type.hpp +62 -0
- data/ext/boost/mpl/aux_/numeric_cast_utils.hpp +77 -0
- data/ext/boost/mpl/aux_/numeric_op.hpp +315 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp +97 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp +97 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/equal_to.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp +180 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/greater.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/greater_equal.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp +133 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp +180 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/less.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/less_equal.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/list.hpp +323 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/minus.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/not_equal_to.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/plus.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp +231 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/times.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/vector.hpp +323 -0
- data/ext/boost/mpl/aux_/preprocessor/default_params.hpp +67 -0
- data/ext/boost/mpl/aux_/push_back_impl.hpp +70 -0
- data/ext/boost/mpl/aux_/push_front_impl.hpp +71 -0
- data/ext/boost/mpl/aux_/reverse_fold_impl.hpp +44 -0
- data/ext/boost/mpl/aux_/size_impl.hpp +52 -0
- data/ext/boost/mpl/aux_/traits_lambda_spec.hpp +63 -0
- data/ext/boost/mpl/back_fwd.hpp +24 -0
- data/ext/boost/mpl/back_inserter.hpp +34 -0
- data/ext/boost/mpl/begin_end.hpp +57 -0
- data/ext/boost/mpl/begin_end_fwd.hpp +27 -0
- data/ext/boost/mpl/clear.hpp +39 -0
- data/ext/boost/mpl/clear_fwd.hpp +24 -0
- data/ext/boost/mpl/comparison.hpp +24 -0
- data/ext/boost/mpl/contains.hpp +41 -0
- data/ext/boost/mpl/contains_fwd.hpp +25 -0
- data/ext/boost/mpl/deref.hpp +41 -0
- data/ext/boost/mpl/distance.hpp +78 -0
- data/ext/boost/mpl/distance_fwd.hpp +28 -0
- data/ext/boost/mpl/empty_fwd.hpp +24 -0
- data/ext/boost/mpl/equal_to.hpp +21 -0
- data/ext/boost/mpl/find.hpp +38 -0
- data/ext/boost/mpl/find_if.hpp +50 -0
- data/ext/boost/mpl/fold.hpp +48 -0
- data/ext/boost/mpl/front_fwd.hpp +24 -0
- data/ext/boost/mpl/front_inserter.hpp +33 -0
- data/ext/boost/mpl/greater.hpp +21 -0
- data/ext/boost/mpl/greater_equal.hpp +21 -0
- data/ext/boost/mpl/inserter.hpp +32 -0
- data/ext/boost/mpl/iter_fold.hpp +49 -0
- data/ext/boost/mpl/iter_fold_if.hpp +117 -0
- data/ext/boost/mpl/iterator_range.hpp +42 -0
- data/ext/boost/mpl/iterator_tags.hpp +27 -0
- data/ext/boost/mpl/less.hpp +21 -0
- data/ext/boost/mpl/less_equal.hpp +21 -0
- data/ext/boost/mpl/limits/list.hpp +21 -0
- data/ext/boost/mpl/limits/vector.hpp +21 -0
- data/ext/boost/mpl/list.hpp +57 -0
- data/ext/boost/mpl/list/aux_/O1_size.hpp +33 -0
- data/ext/boost/mpl/list/aux_/begin_end.hpp +44 -0
- data/ext/boost/mpl/list/aux_/clear.hpp +34 -0
- data/ext/boost/mpl/list/aux_/empty.hpp +34 -0
- data/ext/boost/mpl/list/aux_/front.hpp +33 -0
- data/ext/boost/mpl/list/aux_/include_preprocessed.hpp +35 -0
- data/ext/boost/mpl/list/aux_/item.hpp +55 -0
- data/ext/boost/mpl/list/aux_/iterator.hpp +76 -0
- data/ext/boost/mpl/list/aux_/pop_front.hpp +34 -0
- data/ext/boost/mpl/list/aux_/preprocessed/plain/list10.hpp +149 -0
- data/ext/boost/mpl/list/aux_/preprocessed/plain/list20.hpp +169 -0
- data/ext/boost/mpl/list/aux_/push_back.hpp +36 -0
- data/ext/boost/mpl/list/aux_/push_front.hpp +39 -0
- data/ext/boost/mpl/list/aux_/size.hpp +33 -0
- data/ext/boost/mpl/list/aux_/tag.hpp +24 -0
- data/ext/boost/mpl/list/list0.hpp +42 -0
- data/ext/boost/mpl/list/list10.hpp +43 -0
- data/ext/boost/mpl/list/list20.hpp +43 -0
- data/ext/boost/mpl/long.hpp +22 -0
- data/ext/boost/mpl/long_fwd.hpp +27 -0
- data/ext/boost/mpl/minus.hpp +21 -0
- data/ext/boost/mpl/multiplies.hpp +53 -0
- data/ext/boost/mpl/negate.hpp +81 -0
- data/ext/boost/mpl/not_equal_to.hpp +21 -0
- data/ext/boost/mpl/numeric_cast.hpp +41 -0
- data/ext/boost/mpl/pair.hpp +70 -0
- data/ext/boost/mpl/plus.hpp +21 -0
- data/ext/boost/mpl/pop_back_fwd.hpp +24 -0
- data/ext/boost/mpl/pop_front_fwd.hpp +24 -0
- data/ext/boost/mpl/prior.hpp +19 -0
- data/ext/boost/mpl/push_back.hpp +53 -0
- data/ext/boost/mpl/push_back_fwd.hpp +24 -0
- data/ext/boost/mpl/push_front.hpp +52 -0
- data/ext/boost/mpl/push_front_fwd.hpp +24 -0
- data/ext/boost/mpl/remove_if.hpp +83 -0
- data/ext/boost/mpl/reverse_fold.hpp +50 -0
- data/ext/boost/mpl/same_as.hpp +55 -0
- data/ext/boost/mpl/sequence_tag.hpp +124 -0
- data/ext/boost/mpl/sequence_tag_fwd.hpp +26 -0
- data/ext/boost/mpl/size.hpp +42 -0
- data/ext/boost/mpl/size_fwd.hpp +24 -0
- data/ext/boost/mpl/tag.hpp +52 -0
- data/ext/boost/mpl/times.hpp +21 -0
- data/ext/boost/mpl/vector.hpp +57 -0
- data/ext/boost/mpl/vector/aux_/O1_size.hpp +56 -0
- data/ext/boost/mpl/vector/aux_/at.hpp +116 -0
- data/ext/boost/mpl/vector/aux_/back.hpp +59 -0
- data/ext/boost/mpl/vector/aux_/begin_end.hpp +49 -0
- data/ext/boost/mpl/vector/aux_/clear.hpp +55 -0
- data/ext/boost/mpl/vector/aux_/empty.hpp +68 -0
- data/ext/boost/mpl/vector/aux_/front.hpp +56 -0
- data/ext/boost/mpl/vector/aux_/include_preprocessed.hpp +55 -0
- data/ext/boost/mpl/vector/aux_/item.hpp +103 -0
- data/ext/boost/mpl/vector/aux_/iterator.hpp +130 -0
- data/ext/boost/mpl/vector/aux_/pop_back.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/pop_front.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp +829 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp +1144 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp +139 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp +159 -0
- data/ext/boost/mpl/vector/aux_/push_back.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/push_front.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/size.hpp +49 -0
- data/ext/boost/mpl/vector/aux_/tag.hpp +32 -0
- data/ext/boost/mpl/vector/aux_/vector0.hpp +52 -0
- data/ext/boost/mpl/vector/vector0.hpp +34 -0
- data/ext/boost/mpl/vector/vector10.hpp +45 -0
- data/ext/boost/mpl/vector/vector20.hpp +45 -0
- data/ext/boost/none.hpp +1 -1
- data/ext/boost/numeric/conversion/bounds.hpp +24 -0
- data/ext/boost/numeric/conversion/cast.hpp +61 -0
- data/ext/boost/numeric/conversion/conversion_traits.hpp +39 -0
- data/ext/boost/numeric/conversion/converter.hpp +68 -0
- data/ext/boost/numeric/conversion/converter_policies.hpp +186 -0
- data/ext/boost/numeric/conversion/detail/bounds.hpp +58 -0
- data/ext/boost/numeric/conversion/detail/conversion_traits.hpp +97 -0
- data/ext/boost/numeric/conversion/detail/converter.hpp +602 -0
- data/ext/boost/numeric/conversion/detail/int_float_mixture.hpp +72 -0
- data/ext/boost/numeric/conversion/detail/is_subranged.hpp +234 -0
- data/ext/boost/numeric/conversion/detail/meta.hpp +120 -0
- data/ext/boost/numeric/conversion/detail/numeric_cast_traits.hpp +138 -0
- data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_common.hpp +1741 -0
- data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp +347 -0
- data/ext/boost/numeric/conversion/detail/sign_mixture.hpp +72 -0
- data/ext/boost/numeric/conversion/detail/udt_builtin_mixture.hpp +69 -0
- data/ext/boost/numeric/conversion/int_float_mixture_enum.hpp +29 -0
- data/ext/boost/numeric/conversion/numeric_cast_traits.hpp +31 -0
- data/ext/boost/numeric/conversion/sign_mixture_enum.hpp +29 -0
- data/ext/boost/numeric/conversion/udt_builtin_mixture_enum.hpp +26 -0
- data/ext/boost/operators.hpp +3 -1
- data/ext/boost/optional/optional.hpp +146 -79
- data/ext/boost/optional/optional_fwd.hpp +8 -1
- data/ext/boost/preprocessor/cat.hpp +2 -2
- data/ext/boost/preprocessor/config/config.hpp +39 -4
- data/ext/boost/preprocessor/facilities/intercept.hpp +277 -0
- data/ext/boost/preprocessor/facilities/overload.hpp +25 -0
- data/ext/boost/preprocessor/iteration/detail/iter/forward1.hpp +3 -3
- data/ext/boost/preprocessor/iteration/iterate.hpp +3 -3
- data/ext/boost/preprocessor/punctuation/paren.hpp +23 -0
- data/ext/boost/preprocessor/repetition/enum_shifted_params.hpp +44 -0
- data/ext/boost/preprocessor/seq/cat.hpp +5 -4
- data/ext/boost/preprocessor/seq/size.hpp +0 -1
- data/ext/boost/preprocessor/tuple/eat.hpp +83 -34
- data/ext/boost/preprocessor/tuple/elem.hpp +161 -355
- data/ext/boost/preprocessor/tuple/rem.hpp +110 -48
- data/ext/boost/preprocessor/tuple/to_list.hpp +90 -36
- data/ext/boost/preprocessor/variadic/elem.hpp +94 -0
- data/ext/boost/preprocessor/variadic/size.hpp +30 -0
- data/ext/boost/range/begin.hpp +17 -6
- data/ext/boost/range/concepts.hpp +37 -2
- data/ext/boost/range/detail/safe_bool.hpp +72 -0
- data/ext/boost/range/end.hpp +14 -9
- data/ext/boost/range/iterator_range_core.hpp +120 -12
- data/ext/boost/range/size.hpp +21 -5
- data/ext/boost/smart_ptr/detail/shared_count.hpp +88 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +3 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +142 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +9 -0
- data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +10 -2
- data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +5 -1
- data/ext/boost/smart_ptr/detail/spinlock.hpp +4 -1
- data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +20 -3
- data/ext/boost/smart_ptr/detail/spinlock_pool.hpp +4 -0
- data/ext/boost/smart_ptr/make_shared.hpp +591 -22
- data/ext/boost/smart_ptr/shared_array.hpp +29 -1
- data/ext/boost/smart_ptr/shared_ptr.hpp +29 -13
- data/ext/boost/smart_ptr/weak_ptr.hpp +24 -12
- data/ext/boost/src/pthread/once.cpp +9 -7
- data/ext/boost/src/pthread/thread.cpp +32 -28
- data/ext/boost/src/pthread/timeconv.inl +4 -5
- data/ext/boost/src/tss_null.cpp +5 -1
- data/ext/boost/static_assert.hpp +8 -2
- data/ext/boost/thread/detail/config.hpp +19 -4
- data/ext/boost/thread/detail/move.hpp +11 -5
- data/ext/boost/thread/detail/thread.hpp +59 -43
- data/ext/boost/thread/exceptions.hpp +9 -9
- data/ext/boost/thread/future.hpp +150 -82
- data/ext/boost/thread/locks.hpp +101 -60
- data/ext/boost/thread/pthread/condition_variable.hpp +79 -32
- data/ext/boost/thread/pthread/condition_variable_fwd.hpp +12 -3
- data/ext/boost/thread/pthread/mutex.hpp +17 -14
- data/ext/boost/thread/pthread/once.hpp +3 -4
- data/ext/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +12 -2
- data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -19
- data/ext/boost/thread/pthread/shared_mutex.hpp +13 -13
- data/ext/boost/thread/pthread/thread_data.hpp +40 -12
- data/ext/boost/thread/thread_time.hpp +5 -0
- data/ext/boost/throw_exception.hpp +1 -1
- data/ext/boost/token_functions.hpp +34 -10
- data/ext/boost/type_traits/add_rvalue_reference.hpp +66 -0
- data/ext/boost/type_traits/alignment_of.hpp +1 -1
- data/ext/boost/type_traits/detail/bool_trait_def.hpp +26 -3
- data/ext/boost/type_traits/detail/bool_trait_undef.hpp +3 -2
- data/ext/boost/type_traits/detail/cv_traits_impl.hpp +1 -1
- data/ext/boost/type_traits/detail/size_t_trait_def.hpp +6 -4
- data/ext/boost/type_traits/detail/type_trait_def.hpp +8 -2
- data/ext/boost/type_traits/function_traits.hpp +1 -1
- data/ext/boost/type_traits/has_nothrow_constructor.hpp +53 -0
- data/ext/boost/type_traits/has_nothrow_copy.hpp +19 -5
- data/ext/boost/type_traits/has_trivial_constructor.hpp +51 -0
- data/ext/boost/type_traits/has_trivial_copy.hpp +20 -5
- data/ext/boost/type_traits/has_trivial_destructor.hpp +12 -5
- data/ext/boost/type_traits/intrinsics.hpp +119 -71
- data/ext/boost/type_traits/is_const.hpp +5 -5
- data/ext/boost/type_traits/is_convertible.hpp +14 -13
- data/ext/boost/type_traits/is_enum.hpp +1 -1
- data/ext/boost/type_traits/is_floating_point.hpp +27 -0
- data/ext/boost/type_traits/is_function.hpp +3 -3
- data/ext/boost/type_traits/is_fundamental.hpp +1 -1
- data/ext/boost/type_traits/is_member_function_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_member_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_pod.hpp +11 -3
- data/ext/boost/type_traits/is_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_signed.hpp +8 -3
- data/ext/boost/type_traits/is_union.hpp +8 -0
- data/ext/boost/type_traits/is_unsigned.hpp +9 -4
- data/ext/boost/type_traits/is_volatile.hpp +5 -5
- data/ext/boost/type_traits/remove_cv.hpp +4 -3
- data/ext/boost/type_traits/remove_pointer.hpp +51 -2
- data/ext/boost/type_traits/remove_reference.hpp +2 -2
- data/ext/boost/type_traits/type_with_alignment.hpp +8 -2
- data/ext/boost/utility/declval.hpp +44 -0
- data/ext/boost/utility/detail/in_place_factory_prefix.hpp +36 -0
- data/ext/boost/utility/detail/in_place_factory_suffix.hpp +23 -0
- data/ext/boost/utility/detail/result_of_iterate.hpp +142 -0
- data/ext/boost/utility/in_place_factory.hpp +88 -0
- data/ext/boost/utility/result_of.hpp +103 -0
- data/ext/boost/utility/swap.hpp +55 -0
- data/ext/common/AnsiColorConstants.h +36 -0
- data/ext/common/ApplicationPool2/Common.h +87 -0
- data/ext/common/ApplicationPool2/ComponentInfo.h +53 -0
- data/ext/common/ApplicationPool2/Group.h +648 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +580 -0
- data/ext/common/ApplicationPool2/Options.h +576 -0
- data/ext/common/ApplicationPool2/PipeWatcher.h +61 -0
- data/ext/common/ApplicationPool2/Pool.h +1181 -0
- data/ext/common/ApplicationPool2/Process.h +425 -0
- data/ext/common/ApplicationPool2/README.md +96 -0
- data/ext/common/ApplicationPool2/Session.h +158 -0
- data/ext/common/ApplicationPool2/Socket.h +246 -0
- data/ext/common/ApplicationPool2/Spawner.h +2212 -0
- data/ext/common/ApplicationPool2/SuperGroup.h +749 -0
- data/ext/common/BackgroundEventLoop.cpp +129 -0
- data/ext/common/BackgroundEventLoop.h +61 -0
- data/ext/common/Constants.h +3 -1
- data/ext/common/EventedBufferedInput.h +331 -0
- data/ext/common/EventedMessageServer.h +17 -34
- data/ext/common/EventedServer.h +2 -2
- data/ext/common/Exceptions.h +71 -19
- data/ext/common/FileDescriptor.h +8 -6
- data/ext/common/HttpConstants.h +167 -0
- data/ext/common/IniFile.h +24 -0
- data/ext/common/Logging.h +62 -849
- data/ext/common/MessageReadersWriters.h +19 -0
- data/ext/common/MessageServer.h +11 -14
- data/ext/common/MultiLibeio.cpp +198 -0
- data/ext/common/MultiLibeio.h +67 -0
- data/ext/common/ResourceLocator.h +24 -41
- data/ext/common/SafeLibev.h +186 -14
- data/ext/common/StaticString.h +23 -3
- data/ext/common/UnionStation.h +972 -0
- data/ext/common/Utils.cpp +168 -24
- data/ext/common/Utils.h +25 -3
- data/ext/common/Utils/CachedFileStat.hpp +4 -3
- data/ext/common/Utils/FileChangeChecker.h +2 -2
- data/ext/common/Utils/HashMap.h +50 -0
- data/ext/common/Utils/IOUtils.cpp +229 -68
- data/ext/common/Utils/IOUtils.h +134 -3
- data/ext/common/Utils/Lock.h +28 -0
- data/ext/common/Utils/MemoryBarrier.h +52 -0
- data/ext/common/Utils/PriorityQueue.h +54 -0
- data/ext/common/Utils/ProcessMetricsCollector.h +9 -11
- data/ext/common/Utils/ScopeGuard.h +50 -1
- data/ext/common/Utils/SmallVector.h +653 -0
- data/ext/common/Utils/StrIntUtils.cpp +26 -2
- data/ext/common/Utils/StrIntUtils.h +18 -2
- data/ext/common/Utils/StringMap.h +125 -8
- data/ext/common/Utils/Template.h +212 -0
- data/ext/common/Utils/fib.c +699 -0
- data/ext/common/Utils/fib.h +101 -0
- data/ext/common/Utils/fibpriv.h +67 -0
- data/ext/common/Utils/json-forwards.h +249 -0
- data/ext/common/Utils/json.h +1855 -0
- data/ext/common/Utils/jsoncpp.cpp +4230 -0
- data/ext/common/agents/Base.cpp +1126 -0
- data/ext/common/{AgentBase.h → agents/Base.h} +5 -1
- data/ext/common/agents/EnvPrinter.c +16 -0
- data/ext/common/agents/HelperAgent/AgentOptions.h +81 -0
- data/ext/common/{HelperAgent → agents/HelperAgent}/BacktracesServer.h +3 -2
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +732 -0
- data/ext/common/agents/HelperAgent/Main.cpp +497 -0
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +283 -0
- data/ext/common/agents/HelperAgent/RequestHandler.h +2139 -0
- data/ext/common/agents/HelperAgent/ScgiRequestParser.h +451 -0
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/DataStoreId.h +1 -1
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.cpp +1 -1
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.h +0 -0
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/LoggingServer.h +18 -16
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/Main.cpp +15 -13
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/RemoteSender.h +6 -6
- data/ext/common/agents/SpawnPreparer.cpp +127 -0
- data/ext/common/{Watchdog.cpp → agents/Watchdog/Main.cpp} +63 -25
- data/ext/libeio/Changes +72 -0
- data/ext/{google/COPYING → libeio/LICENSE} +17 -9
- data/ext/libeio/Makefile.am +15 -0
- data/ext/libeio/Makefile.in +694 -0
- data/ext/libeio/aclocal.m4 +9418 -0
- data/ext/libeio/autogen.sh +3 -0
- data/ext/libeio/config.guess +1501 -0
- data/ext/libeio/config.h.in +136 -0
- data/ext/libeio/config.sub +1705 -0
- data/ext/libeio/configure +14822 -0
- data/ext/libeio/configure.ac +22 -0
- data/ext/libeio/demo.c +194 -0
- data/ext/libeio/ecb.h +457 -0
- data/ext/libeio/eio.c +2816 -0
- data/ext/libeio/eio.h +411 -0
- data/ext/libeio/install-sh +520 -0
- data/ext/libeio/libeio.m4 +211 -0
- data/ext/libeio/ltmain.sh +9636 -0
- data/ext/libeio/missing +376 -0
- data/ext/libeio/xthread.h +166 -0
- data/ext/libev/Changes +125 -7
- data/ext/libev/Makefile.am +5 -3
- data/ext/libev/Makefile.in +209 -120
- data/ext/libev/aclocal.m4 +6027 -4619
- data/ext/libev/autogen.sh +1 -4
- data/ext/libev/config.h.in +11 -7
- data/ext/libev/configure +7312 -14993
- data/ext/libev/configure.ac +12 -5
- data/ext/libev/depcomp +630 -0
- data/ext/libev/ev++.h +48 -32
- data/ext/libev/ev.c +1173 -391
- data/ext/libev/ev.h +315 -181
- data/ext/libev/ev_epoll.c +66 -15
- data/ext/libev/ev_kqueue.c +20 -18
- data/ext/libev/ev_poll.c +27 -23
- data/ext/libev/ev_port.c +39 -19
- data/ext/libev/ev_select.c +23 -17
- data/ext/libev/ev_vars.h +25 -8
- data/ext/libev/ev_win32.c +6 -6
- data/ext/libev/ev_wrap.h +22 -2
- data/ext/libev/event.c +18 -17
- data/ext/libev/event.h +16 -4
- data/ext/libev/libev.m4 +10 -6
- data/ext/libev/ltmain.sh +7353 -5811
- data/ext/nginx/Configuration.c +74 -42
- data/ext/nginx/Configuration.h +3 -5
- data/ext/nginx/ContentHandler.c +26 -83
- data/ext/nginx/ContentHandler.h +1 -1
- data/ext/nginx/config +13 -9
- data/ext/nginx/ngx_http_passenger_module.c +3 -7
- data/ext/oxt/detail/backtrace_enabled.hpp +5 -102
- data/ext/oxt/detail/context.hpp +90 -0
- data/ext/oxt/detail/spin_lock_darwin.hpp +4 -0
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +4 -0
- data/ext/oxt/detail/spin_lock_pthreads.hpp +14 -0
- data/ext/oxt/detail/tracable_exception_enabled.hpp +2 -2
- data/ext/oxt/dynamic_thread_group.hpp +27 -1
- data/ext/oxt/implementation.cpp +415 -0
- data/ext/oxt/{thread.cpp → initialize.hpp} +13 -6
- data/ext/oxt/macros.hpp +32 -1
- data/ext/oxt/spin_lock.hpp +6 -11
- data/ext/oxt/system_calls.cpp +204 -16
- data/ext/oxt/system_calls.hpp +85 -45
- data/ext/oxt/thread.hpp +13 -117
- data/ext/ruby/passenger_native_support.c +82 -237
- data/helper-scripts/backtrace-sanitizer.rb +114 -0
- data/helper-scripts/classic-rails-loader.rb +135 -0
- data/helper-scripts/classic-rails-preloader.rb +161 -0
- data/helper-scripts/node-loader.js +314 -0
- data/helper-scripts/rack-loader.rb +104 -0
- data/helper-scripts/rack-preloader.rb +132 -0
- data/helper-scripts/wsgi-loader.py +231 -0
- data/helper-scripts/wsgi-preloader.py +1 -0
- data/lib/phusion_passenger.rb +159 -61
- data/lib/phusion_passenger/abstract_installer.rb +182 -87
- data/lib/phusion_passenger/admin_tools/server_instance.rb +25 -19
- data/lib/phusion_passenger/analytics_logger.rb +5 -4
- data/lib/phusion_passenger/classic_rails/{request_handler.rb → thread_handler_extension.rb} +4 -40
- data/lib/phusion_passenger/classic_rails_extensions/init.rb +5 -3
- data/lib/phusion_passenger/common_library.rb +441 -0
- data/lib/phusion_passenger/console_text_template.rb +4 -16
- data/lib/phusion_passenger/constants.rb +1 -8
- data/lib/phusion_passenger/debug_logging.rb +5 -2
- data/lib/phusion_passenger/dependencies.rb +51 -13
- data/lib/phusion_passenger/loader_shared_helpers.rb +318 -0
- data/lib/phusion_passenger/message_channel.rb +3 -47
- data/lib/phusion_passenger/message_client.rb +2 -2
- data/lib/phusion_passenger/native_support.rb +36 -15
- data/lib/phusion_passenger/packaging.rb +8 -11
- data/lib/phusion_passenger/platform_info.rb +25 -17
- data/lib/phusion_passenger/platform_info/apache.rb +10 -7
- data/lib/phusion_passenger/platform_info/binary_compatibility.rb +10 -30
- data/lib/phusion_passenger/platform_info/compiler.rb +93 -34
- data/lib/phusion_passenger/platform_info/ruby.rb +37 -97
- data/lib/phusion_passenger/preloader_shared_helpers.rb +121 -0
- data/lib/phusion_passenger/public_api.rb +1 -4
- data/lib/phusion_passenger/rack/{request_handler.rb → thread_handler_extension.rb} +14 -63
- data/lib/phusion_passenger/rails3_extensions/init.rb +9 -8
- data/lib/phusion_passenger/request_handler.rb +500 -0
- data/lib/phusion_passenger/request_handler/thread_handler.rb +360 -0
- data/lib/phusion_passenger/ruby_core_enhancements.rb +142 -0
- data/lib/phusion_passenger/standalone/command.rb +36 -15
- data/lib/phusion_passenger/standalone/package_runtime_command.rb +16 -8
- data/lib/phusion_passenger/standalone/runtime_installer.rb +169 -72
- data/lib/phusion_passenger/standalone/start_command.rb +44 -39
- data/lib/phusion_passenger/standalone/utils.rb +5 -5
- data/lib/phusion_passenger/utils.rb +35 -914
- data/lib/phusion_passenger/utils/ansi_colors.rb +59 -0
- data/lib/phusion_passenger/utils/file_system_watcher.rb +1 -1
- data/lib/phusion_passenger/utils/robust_interruption.rb +134 -0
- data/lib/phusion_passenger/utils/tee_input.rb +174 -0
- data/lib/phusion_passenger/utils/tmpio.rb +33 -0
- data/lib/phusion_passenger/utils/unseekable_socket.rb +6 -0
- data/resources/mime.types +5 -1
- data/{lib/phusion_passenger/templates → resources}/standalone_default_root/index.html +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/config_snippets.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/deployment_example.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/no_write_permission_to_passenger_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/welcome.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/error_layout.css +6 -0
- data/resources/templates/error_layout.html.template +89 -0
- data/resources/templates/general_error.html.template +1 -0
- data/resources/templates/general_error_with_html.html.template +1 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/ask_for_extra_configure_flags.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/cannot_write_to_dir.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets_inserted.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/confirm_extra_configure_flags.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/deployment_example.txt.erb +0 -0
- data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +8 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_downloaded.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_extracted.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/query_download_and_install.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/welcome.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/cannot_write_to_dir.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/config.erb +26 -5
- data/{lib/phusion_passenger → resources}/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/welcome.txt.erb +0 -0
- data/resources/templates/undisclosed_error.html.template +25 -0
- data/test/config.json.example +42 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +86 -0
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +44 -0
- data/test/cxx/ApplicationPool2/PoolTest.cpp +1234 -0
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +131 -0
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +229 -0
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +744 -0
- data/test/cxx/BufferedIOTest.cpp +7 -7
- data/test/cxx/CxxTestMain.cpp +65 -2
- data/test/cxx/FileBackedPipeTest.cpp +626 -0
- data/test/cxx/FileChangeCheckerTest.cpp +20 -18
- data/test/cxx/FilterSupportTest.cpp +5 -5
- data/test/cxx/IOUtilsTest.cpp +11 -4
- data/test/cxx/MessageReadersWritersTest.cpp +1 -1
- data/test/cxx/MessageServerTest.cpp +31 -30
- data/test/cxx/RequestHandlerTest.cpp +777 -0
- data/test/cxx/ScgiRequestParserTest.cpp +36 -16
- data/test/cxx/ServerInstanceDirTest.cpp +1 -1
- data/test/cxx/StringMapTest.cpp +61 -0
- data/test/cxx/TemplateTest.cpp +118 -0
- data/test/cxx/TestSupport.cpp +25 -68
- data/test/cxx/TestSupport.h +81 -41
- data/test/cxx/{LoggingTest.cpp → UnionStationTest.cpp} +79 -74
- data/test/cxx/UtilsTest.cpp +59 -5
- data/test/integration_tests/apache2_tests.rb +2 -2
- data/test/integration_tests/nginx_tests.rb +1 -1
- data/test/integration_tests/spec_helper.rb +7 -5
- data/test/oxt/oxt_test_main.cpp +2 -0
- data/test/oxt/syscall_interruption_test.cpp +1 -0
- data/test/ruby/classic_rails/loader_spec.rb +48 -0
- data/test/ruby/classic_rails/preloader_spec.rb +54 -0
- data/test/ruby/rack/loader_spec.rb +62 -0
- data/test/ruby/rack/preloader_spec.rb +74 -0
- data/test/ruby/{abstract_request_handler_spec.rb → request_handler_spec.rb} +31 -68
- data/test/ruby/shared/loader_spec.rb +241 -0
- data/test/ruby/shared/rails/analytics_logging_extensions_spec.rb +141 -182
- data/test/ruby/shared/ruby_loader_spec.rb +55 -0
- data/test/ruby/spec_helper.rb +8 -53
- data/test/ruby/utils/file_system_watcher_spec.rb +9 -1
- data/test/ruby/utils_spec.rb +10 -683
- data/test/stub/rack/config.ru +28 -3
- data/test/stub/rack/start.rb +47 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/Rakefile +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/application_controller.rb +0 -2
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_1.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_2.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/foo_controller.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/database.yml +3 -3
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environment.rb +5 -2
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/staging.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/routes.rb +1 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/about +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/console +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/dbconsole +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/destroy +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/generate +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/benchmarker +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/profiler +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/request +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/plugin +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/inspector +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/reaper +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/spawner +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/runner +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/server +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/Gemfile +0 -0
- data/test/stub/rails3.0/Gemfile.lock +80 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/Rakefile +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/controllers/application_controller.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/views/layouts/application.html.erb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config.ru +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/application.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/database.yml +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environment.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/test.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/backtrace_silencers.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/passenger.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/secret_token.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/session_store.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/locales/en.yml +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/routes.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/db/seeds.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/doc/README_FOR_APP +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/404.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/422.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/500.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/favicon.ico +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/index.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/robots.txt +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/script/rails +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/performance/browsing_test.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/test_helper.rb +0 -0
- data/test/stub/start_error.pl +24 -0
- data/test/stub/wsgi/passenger_wsgi.py +71 -3
- data/test/support/apache2_controller.rb +2 -2
- data/test/support/placebo-preloader.rb +88 -0
- data/test/support/test_helper.rb +1 -14
- data/test/tut/tut.h +11 -4
- metadata +590 -326
- data.tar.gz.asc +0 -12
- data/PACKAGING.TXT +0 -25
- data/build/config.rb +0 -46
- data/ext/apache2/HelperAgent.cpp +0 -364
- data/ext/boost/call_traits.hpp +0 -24
- data/ext/boost/detail/call_traits.hpp +0 -164
- data/ext/common/AbstractSpawnManager.h +0 -110
- data/ext/common/AgentBase.cpp +0 -432
- data/ext/common/ApplicationPool/Client.h +0 -788
- data/ext/common/ApplicationPool/Interface.h +0 -295
- data/ext/common/ApplicationPool/Pool.h +0 -1327
- data/ext/common/ApplicationPool/Server.h +0 -479
- data/ext/common/MessageChannel.h +0 -494
- data/ext/common/PoolOptions.h +0 -518
- data/ext/common/Process.h +0 -253
- data/ext/common/Session.h +0 -436
- data/ext/common/SpawnManager.h +0 -611
- data/ext/google/ChangeLog +0 -167
- data/ext/google/dense_hash_map +0 -310
- data/ext/google/dense_hash_set +0 -287
- data/ext/google/sparse_hash_map +0 -294
- data/ext/google/sparse_hash_set +0 -275
- data/ext/google/sparsehash/densehashtable.h +0 -1062
- data/ext/google/sparsehash/sparseconfig.h +0 -55
- data/ext/google/sparsehash/sparsehashtable.h +0 -1015
- data/ext/google/sparsetable +0 -1468
- data/ext/google/type_traits.h +0 -250
- data/ext/nginx/HelperAgent.cpp +0 -1355
- data/ext/nginx/ScgiRequestParser.h +0 -375
- data/ext/oxt/backtrace.cpp +0 -185
- data/ext/oxt/tracable_exception.cpp +0 -89
- data/helper-scripts/passenger-spawn-server +0 -106
- data/lib/phusion_passenger/abstract_request_handler.rb +0 -766
- data/lib/phusion_passenger/abstract_server.rb +0 -372
- data/lib/phusion_passenger/abstract_server_collection.rb +0 -335
- data/lib/phusion_passenger/app_process.rb +0 -174
- data/lib/phusion_passenger/classic_rails/application_spawner.rb +0 -344
- data/lib/phusion_passenger/classic_rails/framework_spawner.rb +0 -311
- data/lib/phusion_passenger/exceptions.rb +0 -103
- data/lib/phusion_passenger/html_template.rb +0 -107
- data/lib/phusion_passenger/rack/application_spawner.rb +0 -231
- data/lib/phusion_passenger/spawn_manager.rb +0 -359
- data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +0 -38
- data/lib/phusion_passenger/templates/app_init_error.html.erb +0 -64
- data/lib/phusion_passenger/templates/database_error.html.erb +0 -66
- data/lib/phusion_passenger/templates/error_layout.html.erb +0 -39
- data/lib/phusion_passenger/templates/framework_init_error.html.erb +0 -39
- data/lib/phusion_passenger/templates/general_error.html.erb +0 -22
- data/lib/phusion_passenger/templates/load_error.html.erb +0 -46
- data/lib/phusion_passenger/templates/version_not_found.html.erb +0 -34
- data/lib/phusion_passenger/utils/rewindable_input.rb +0 -125
- data/lib/phusion_passenger/wsgi/application_spawner.rb +0 -108
- data/test/config.yml.example +0 -41
- data/test/cxx/ApplicationPool_PoolTest.cpp +0 -33
- data/test/cxx/ApplicationPool_PoolTestCases.cpp +0 -1029
- data/test/cxx/ApplicationPool_ServerTest.cpp +0 -308
- data/test/cxx/ApplicationPool_Server_PoolTest.cpp +0 -80
- data/test/cxx/MessageChannelTest.cpp +0 -557
- data/test/cxx/PoolOptionsTest.cpp +0 -116
- data/test/cxx/SpawnManagerTest.cpp +0 -161
- data/test/ruby/abstract_server_collection_spec.rb +0 -247
- data/test/ruby/abstract_server_spec.rb +0 -61
- data/test/ruby/app_process_spec.rb +0 -43
- data/test/ruby/classic_rails/application_spawner_spec.rb +0 -89
- data/test/ruby/classic_rails/framework_spawner_spec.rb +0 -92
- data/test/ruby/rack/application_spawner_spec.rb +0 -116
- data/test/ruby/shared/abstract_server_spec.rb +0 -23
- data/test/ruby/shared/spawners/classic_rails/framework_spawner_spec.rb +0 -38
- data/test/ruby/shared/spawners/classic_rails/lack_of_rails_gem_version_spec.rb +0 -19
- data/test/ruby/shared/spawners/classic_rails/spawner_spec.rb +0 -15
- data/test/ruby/shared/spawners/non_preloading_spawner_spec.rb +0 -27
- data/test/ruby/shared/spawners/preloading_spawner_spec.rb +0 -29
- data/test/ruby/shared/spawners/reload_all_spec.rb +0 -36
- data/test/ruby/shared/spawners/reload_single_spec.rb +0 -52
- data/test/ruby/shared/spawners/spawn_server_spec.rb +0 -28
- data/test/ruby/shared/spawners/spawner_spec.rb +0 -273
- data/test/ruby/shared/utils/pseudo_io_spec.rb +0 -60
- data/test/ruby/spawn_manager_spec.rb +0 -134
- data/test/ruby/wsgi/application_spawner_spec.rb +0 -50
- data/test/stub/message_channel.rb +0 -11
- data/test/stub/message_channel_2.rb +0 -12
- data/test/stub/message_channel_3.rb +0 -19
- data/test/stub/rails_apps/3.0/empty/Gemfile.lock +0 -73
- data/test/stub/spawn_server.rb +0 -22
- metadata.gz.asc +0 -12
data/ext/common/SafeLibev.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - http://www.modrails.com/
|
3
|
-
* Copyright (c) 2010 Phusion
|
3
|
+
* Copyright (c) 2010, 2011, 2012 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -27,7 +27,11 @@
|
|
27
27
|
|
28
28
|
#include <ev++.h>
|
29
29
|
#include <vector>
|
30
|
+
#include <list>
|
31
|
+
#include <memory>
|
32
|
+
#include <climits>
|
30
33
|
#include <boost/thread.hpp>
|
34
|
+
#include <boost/shared_ptr.hpp>
|
31
35
|
#include <boost/function.hpp>
|
32
36
|
#include <boost/bind.hpp>
|
33
37
|
|
@@ -43,25 +47,67 @@ using namespace boost;
|
|
43
47
|
class SafeLibev {
|
44
48
|
private:
|
45
49
|
typedef function<void ()> Callback;
|
50
|
+
|
51
|
+
struct Command {
|
52
|
+
int id;
|
53
|
+
Callback callback;
|
54
|
+
|
55
|
+
Command(unsigned int _id, const Callback &_callback)
|
56
|
+
: id(_id),
|
57
|
+
callback(_callback)
|
58
|
+
{ }
|
59
|
+
};
|
60
|
+
|
61
|
+
struct Timer {
|
62
|
+
ev_timer realTimer;
|
63
|
+
SafeLibev *self;
|
64
|
+
Callback callback;
|
65
|
+
list<Timer *>::iterator it;
|
66
|
+
|
67
|
+
Timer(SafeLibev *_self, const Callback &_callback)
|
68
|
+
: self(_self),
|
69
|
+
callback(_callback)
|
70
|
+
{ }
|
71
|
+
};
|
46
72
|
|
47
73
|
struct ev_loop *loop;
|
48
74
|
pthread_t loopThread;
|
49
75
|
ev_async async;
|
76
|
+
ev_idle idle;
|
77
|
+
list<Timer *> timers;
|
50
78
|
|
51
79
|
boost::mutex syncher;
|
52
80
|
condition_variable cond;
|
53
|
-
vector<
|
81
|
+
vector<Command> commands;
|
82
|
+
unsigned int nextCommandId;
|
54
83
|
|
55
84
|
static void asyncHandler(EV_P_ ev_async *w, int revents) {
|
56
85
|
SafeLibev *self = (SafeLibev *) w->data;
|
57
|
-
|
58
|
-
|
59
|
-
|
86
|
+
self->runCommands();
|
87
|
+
}
|
88
|
+
|
89
|
+
static void idleHandler(EV_P_ ev_idle *idle, int revents) {
|
90
|
+
SafeLibev *self = (SafeLibev *) idle->data;
|
91
|
+
self->runCommands();
|
92
|
+
}
|
93
|
+
|
94
|
+
static void timeoutHandler(EV_P_ ev_timer *t, int revents) {
|
95
|
+
auto_ptr<Timer> timer((Timer *) ((const char *) t));
|
96
|
+
SafeLibev *self = timer->self;
|
97
|
+
self->timers.erase(timer->it);
|
98
|
+
ev_timer_stop(self->loop, &timer->realTimer);
|
99
|
+
timer->callback();
|
100
|
+
}
|
101
|
+
|
102
|
+
void runCommands() {
|
103
|
+
unique_lock<boost::mutex> l(syncher);
|
104
|
+
vector<Command> commands = this->commands;
|
105
|
+
this->commands.clear();
|
60
106
|
l.unlock();
|
61
107
|
|
62
|
-
vector<
|
63
|
-
for (it = commands.begin(); it !=
|
64
|
-
|
108
|
+
vector<Command>::const_iterator it, end = commands.end();
|
109
|
+
for (it = commands.begin(); it != end; it++) {
|
110
|
+
it->callback();
|
65
111
|
}
|
66
112
|
}
|
67
113
|
|
@@ -82,23 +128,67 @@ private:
|
|
82
128
|
cond.notify_all();
|
83
129
|
}
|
84
130
|
|
131
|
+
void runAndNotify(const Callback *callback, bool *done) {
|
132
|
+
(*callback)();
|
133
|
+
unique_lock<boost::mutex> l(syncher);
|
134
|
+
*done = true;
|
135
|
+
cond.notify_all();
|
136
|
+
}
|
137
|
+
|
138
|
+
void incNextCommandId() {
|
139
|
+
if (nextCommandId == INT_MAX) {
|
140
|
+
nextCommandId = 0;
|
141
|
+
} else {
|
142
|
+
nextCommandId++;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
85
146
|
public:
|
147
|
+
/** SafeLibev takes over ownership of the loop object. */
|
86
148
|
SafeLibev(struct ev_loop *loop) {
|
87
149
|
this->loop = loop;
|
88
150
|
loopThread = pthread_self();
|
151
|
+
nextCommandId = 0;
|
152
|
+
|
89
153
|
ev_async_init(&async, asyncHandler);
|
90
154
|
async.data = this;
|
91
155
|
ev_async_start(loop, &async);
|
156
|
+
|
157
|
+
ev_idle_init(&idle, idleHandler);
|
158
|
+
ev_set_priority(&idle, EV_MAXPRI);
|
159
|
+
idle.data = this;
|
92
160
|
}
|
93
161
|
|
94
162
|
~SafeLibev() {
|
163
|
+
destroy();
|
164
|
+
ev_loop_destroy(loop);
|
165
|
+
}
|
166
|
+
|
167
|
+
void destroy() {
|
95
168
|
ev_async_stop(loop, &async);
|
169
|
+
ev_idle_stop(loop, &idle);
|
170
|
+
|
171
|
+
list<Timer *>::iterator it, end = timers.end();
|
172
|
+
for (it = timers.begin(); it != end; it++) {
|
173
|
+
Timer *timer = *it;
|
174
|
+
ev_timer_stop(loop, &timer->realTimer);
|
175
|
+
delete timer;
|
176
|
+
}
|
177
|
+
timers.clear();
|
96
178
|
}
|
97
179
|
|
98
180
|
struct ev_loop *getLoop() const {
|
99
181
|
return loop;
|
100
182
|
}
|
101
183
|
|
184
|
+
void setCurrentThread() {
|
185
|
+
loopThread = pthread_self();
|
186
|
+
}
|
187
|
+
|
188
|
+
pthread_t getCurrentThread() const {
|
189
|
+
return loopThread;
|
190
|
+
}
|
191
|
+
|
102
192
|
template<typename Watcher>
|
103
193
|
void start(Watcher &watcher) {
|
104
194
|
if (pthread_equal(pthread_self(), loopThread)) {
|
@@ -107,8 +197,10 @@ public:
|
|
107
197
|
} else {
|
108
198
|
unique_lock<boost::mutex> l(syncher);
|
109
199
|
bool done = false;
|
110
|
-
commands.push_back(
|
111
|
-
|
200
|
+
commands.push_back(Command(nextCommandId,
|
201
|
+
boost::bind(&SafeLibev::startWatcherAndNotify<Watcher>,
|
202
|
+
this, &watcher, &done)));
|
203
|
+
incNextCommandId();
|
112
204
|
ev_async_send(loop, &async);
|
113
205
|
while (!done) {
|
114
206
|
cond.wait(l);
|
@@ -123,8 +215,10 @@ public:
|
|
123
215
|
} else {
|
124
216
|
unique_lock<boost::mutex> l(syncher);
|
125
217
|
bool done = false;
|
126
|
-
commands.push_back(
|
127
|
-
|
218
|
+
commands.push_back(Command(nextCommandId,
|
219
|
+
boost::bind(&SafeLibev::stopWatcherAndNotify<Watcher>,
|
220
|
+
this, &watcher, &done)));
|
221
|
+
incNextCommandId();
|
128
222
|
ev_async_send(loop, &async);
|
129
223
|
while (!done) {
|
130
224
|
cond.wait(l);
|
@@ -133,16 +227,94 @@ public:
|
|
133
227
|
}
|
134
228
|
|
135
229
|
void run(const Callback &callback) {
|
230
|
+
assert(callback != NULL);
|
136
231
|
if (pthread_equal(pthread_self(), loopThread)) {
|
137
232
|
callback();
|
138
233
|
} else {
|
234
|
+
runSync(callback);
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
void runSync(const Callback &callback) {
|
239
|
+
assert(callback != NULL);
|
240
|
+
unique_lock<boost::mutex> l(syncher);
|
241
|
+
bool done = false;
|
242
|
+
commands.push_back(Command(nextCommandId,
|
243
|
+
boost::bind(&SafeLibev::runAndNotify, this,
|
244
|
+
&callback, &done)));
|
245
|
+
incNextCommandId();
|
246
|
+
ev_async_send(loop, &async);
|
247
|
+
while (!done) {
|
248
|
+
cond.wait(l);
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
void runAsync(const Callback &callback) {
|
253
|
+
runLaterTS(callback);
|
254
|
+
}
|
255
|
+
|
256
|
+
// TODO: make it possible to call this from a thread
|
257
|
+
void runAfter(unsigned int timeout, const Callback &callback) {
|
258
|
+
assert(callback != NULL);
|
259
|
+
Timer *timer = new Timer(this, callback);
|
260
|
+
ev_timer_init(&timer->realTimer, timeoutHandler, timeout / 1000.0, 0);
|
261
|
+
timers.push_front(timer);
|
262
|
+
timer->it = timers.begin();
|
263
|
+
ev_timer_start(loop, &timer->realTimer);
|
264
|
+
}
|
265
|
+
|
266
|
+
unsigned int runLater(const Callback &callback) {
|
267
|
+
assert(callback != NULL);
|
268
|
+
unsigned int result;
|
269
|
+
{
|
139
270
|
unique_lock<boost::mutex> l(syncher);
|
140
|
-
commands.push_back(callback);
|
141
|
-
|
271
|
+
commands.push_back(Command(nextCommandId, callback));
|
272
|
+
result = nextCommandId;
|
273
|
+
incNextCommandId();
|
274
|
+
}
|
275
|
+
if (!ev_is_active(&idle)) {
|
276
|
+
ev_idle_start(loop, &idle);
|
277
|
+
}
|
278
|
+
return result;
|
279
|
+
}
|
280
|
+
|
281
|
+
unsigned int runLaterTS(const Callback &callback) {
|
282
|
+
assert(callback != NULL);
|
283
|
+
unsigned int result;
|
284
|
+
{
|
285
|
+
unique_lock<boost::mutex> l(syncher);
|
286
|
+
commands.push_back(Command(nextCommandId, callback));
|
287
|
+
result = nextCommandId;
|
288
|
+
incNextCommandId();
|
142
289
|
}
|
290
|
+
ev_async_send(loop, &async);
|
291
|
+
return result;
|
292
|
+
}
|
293
|
+
|
294
|
+
/**
|
295
|
+
* Cancels a callback that was scheduled to be run by runLater() and runLaterTS().
|
296
|
+
* Returns whether the command has been successfully cancelled or not.
|
297
|
+
* That is, a return value of true guarantees that the callback will not be called
|
298
|
+
* in the future, while a return value of false means that the callback has already
|
299
|
+
* been called or is currently being called.
|
300
|
+
*/
|
301
|
+
bool cancelCommand(int id) {
|
302
|
+
unique_lock<boost::mutex> l(syncher);
|
303
|
+
// TODO: we can do a binary search because the command ID
|
304
|
+
// is monotically increasing except on overflow.
|
305
|
+
vector<Command>::iterator it, end = commands.end();
|
306
|
+
for (it = commands.begin(); it != end; it++) {
|
307
|
+
if (it->id == id) {
|
308
|
+
commands.erase(it);
|
309
|
+
return true;
|
310
|
+
}
|
311
|
+
}
|
312
|
+
return false;
|
143
313
|
}
|
144
314
|
};
|
145
315
|
|
316
|
+
typedef shared_ptr<SafeLibev> SafeLibevPtr;
|
317
|
+
|
146
318
|
|
147
319
|
} // namespace Passenger
|
148
320
|
|
data/ext/common/StaticString.h
CHANGED
@@ -82,10 +82,30 @@ public:
|
|
82
82
|
/** A hash function object for StaticString. */
|
83
83
|
struct Hash {
|
84
84
|
size_t operator()(const StaticString &str) const {
|
85
|
-
size_t result = 0;
|
86
85
|
const char *data = str.content;
|
87
|
-
const char *end =
|
88
|
-
|
86
|
+
const char *end = str.content + str.len;
|
87
|
+
size_t result = 0;
|
88
|
+
|
89
|
+
#if defined(__i386__) || defined(__x86_64__)
|
90
|
+
/* When on x86 or x86_64, process 4 or 8 bytes
|
91
|
+
* per iteration by treating the data as an
|
92
|
+
* array of longs. Luckily for us these
|
93
|
+
* architectures can read longs even on unaligned
|
94
|
+
* addresses.
|
95
|
+
*/
|
96
|
+
const char *last_long = str.content +
|
97
|
+
str.len / sizeof(unsigned long) *
|
98
|
+
sizeof(unsigned long);
|
99
|
+
|
100
|
+
while (data < last_long) {
|
101
|
+
result = result * 33 + *((unsigned long *) data);
|
102
|
+
data += sizeof(unsigned long);
|
103
|
+
}
|
104
|
+
|
105
|
+
/* Process leftover data byte-by-byte. */
|
106
|
+
#endif
|
107
|
+
|
108
|
+
while (data < end) {
|
89
109
|
result = result * 33 + *data;
|
90
110
|
data++;
|
91
111
|
}
|
@@ -0,0 +1,972 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - http://www.modrails.com/
|
3
|
+
* Copyright (c) 2010, 2011, 2012 Phusion
|
4
|
+
*
|
5
|
+
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
12
|
+
* furnished to do so, subject to the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
15
|
+
* all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
* THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
#ifndef _PASSENGER_UNION_STATION_H_
|
26
|
+
#define _PASSENGER_UNION_STATION_H_
|
27
|
+
|
28
|
+
#include <boost/shared_ptr.hpp>
|
29
|
+
#include <boost/enable_shared_from_this.hpp>
|
30
|
+
#include <boost/noncopyable.hpp>
|
31
|
+
#include <oxt/thread.hpp>
|
32
|
+
#include <oxt/system_calls.hpp>
|
33
|
+
#include <oxt/backtrace.hpp>
|
34
|
+
|
35
|
+
#include <sys/types.h>
|
36
|
+
#include <sys/time.h>
|
37
|
+
#include <sys/resource.h>
|
38
|
+
#include <unistd.h>
|
39
|
+
#include <fcntl.h>
|
40
|
+
#include <pthread.h>
|
41
|
+
#include <string>
|
42
|
+
#include <map>
|
43
|
+
#include <stdexcept>
|
44
|
+
#include <cstdio>
|
45
|
+
#include <ctime>
|
46
|
+
#include <cerrno>
|
47
|
+
#include <cassert>
|
48
|
+
|
49
|
+
#include <RandomGenerator.h>
|
50
|
+
#include <FileDescriptor.h>
|
51
|
+
#include <StaticString.h>
|
52
|
+
#include <Logging.h>
|
53
|
+
#include <Exceptions.h>
|
54
|
+
#include <Utils.h>
|
55
|
+
#include <Utils/MessageIO.h>
|
56
|
+
#include <Utils/StrIntUtils.h>
|
57
|
+
#include <Utils/MD5.h>
|
58
|
+
#include <Utils/SystemTime.h>
|
59
|
+
|
60
|
+
|
61
|
+
namespace Passenger {
|
62
|
+
namespace UnionStation {
|
63
|
+
|
64
|
+
using namespace std;
|
65
|
+
using namespace boost;
|
66
|
+
using namespace oxt;
|
67
|
+
|
68
|
+
|
69
|
+
// All access to the file descriptor must be synchronized through the lock.
|
70
|
+
struct Connection {
|
71
|
+
mutable boost::mutex syncher;
|
72
|
+
int fd;
|
73
|
+
|
74
|
+
Connection(int _fd)
|
75
|
+
: fd(_fd)
|
76
|
+
{ }
|
77
|
+
|
78
|
+
~Connection() {
|
79
|
+
disconnect();
|
80
|
+
}
|
81
|
+
|
82
|
+
bool connected() const {
|
83
|
+
return fd != -1;
|
84
|
+
}
|
85
|
+
|
86
|
+
bool disconnect(string &errorResponse) {
|
87
|
+
if (!connected()) {
|
88
|
+
return false;
|
89
|
+
}
|
90
|
+
|
91
|
+
/* The server might send an "error" array message
|
92
|
+
* just before disconnecting. Try to read it.
|
93
|
+
*/
|
94
|
+
TRACE_POINT();
|
95
|
+
vector<string> response;
|
96
|
+
try {
|
97
|
+
unsigned long long timeout = 20000000;
|
98
|
+
while (true) {
|
99
|
+
response = readArrayMessage(fd, &timeout);
|
100
|
+
}
|
101
|
+
} catch (const TimeoutException &) {
|
102
|
+
/* This means that the last message isn't an array
|
103
|
+
* message or that the server didn't send it quickly
|
104
|
+
* enough. In any case, discard whatever previous
|
105
|
+
* array messages we were able to read because they're
|
106
|
+
* guaranteed not to be the error message we're expecting.
|
107
|
+
*/
|
108
|
+
response.clear();
|
109
|
+
} catch (const SystemException &e) {
|
110
|
+
/* We treat ECONNRESET the same as EOFException.
|
111
|
+
* Other errors are treated as TimeoutException.
|
112
|
+
*/
|
113
|
+
if (e.code() != ECONNRESET) {
|
114
|
+
response.clear();
|
115
|
+
}
|
116
|
+
} catch (const EOFException &) {
|
117
|
+
/* Do nothing. We've successfully read the last array message. */
|
118
|
+
}
|
119
|
+
|
120
|
+
UPDATE_TRACE_POINT();
|
121
|
+
disconnect();
|
122
|
+
|
123
|
+
if (response.size() == 2 && response[0] == "error") {
|
124
|
+
errorResponse = response[1];
|
125
|
+
return true;
|
126
|
+
} else {
|
127
|
+
return false;
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
void disconnect() {
|
132
|
+
if (fd != -1) {
|
133
|
+
this_thread::disable_interruption di;
|
134
|
+
this_thread::disable_syscall_interruption dsi;
|
135
|
+
safelyClose(fd);
|
136
|
+
fd = -1;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
};
|
140
|
+
|
141
|
+
typedef shared_ptr<Connection> ConnectionPtr;
|
142
|
+
|
143
|
+
|
144
|
+
/** A special lock type for Connection that also keeps a smart
|
145
|
+
* pointer to the data structure so that the mutex is not destroyed
|
146
|
+
* prematurely.
|
147
|
+
*/
|
148
|
+
struct ConnectionLock {
|
149
|
+
ConnectionPtr connection;
|
150
|
+
bool locked;
|
151
|
+
|
152
|
+
ConnectionLock(const ConnectionPtr &c)
|
153
|
+
: connection(c)
|
154
|
+
{
|
155
|
+
c->syncher.lock();
|
156
|
+
locked = true;
|
157
|
+
}
|
158
|
+
|
159
|
+
~ConnectionLock() {
|
160
|
+
if (locked) {
|
161
|
+
connection->syncher.unlock();
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
void reset(const ConnectionPtr &c, bool lockNow = true) {
|
166
|
+
if (locked) {
|
167
|
+
connection->syncher.unlock();
|
168
|
+
}
|
169
|
+
connection = c;
|
170
|
+
if (lockNow) {
|
171
|
+
connection->syncher.lock();
|
172
|
+
locked = true;
|
173
|
+
} else {
|
174
|
+
locked = false;
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
void lock() {
|
179
|
+
assert(!locked);
|
180
|
+
connection->syncher.lock();
|
181
|
+
locked = true;
|
182
|
+
}
|
183
|
+
};
|
184
|
+
|
185
|
+
|
186
|
+
/**
|
187
|
+
* A scope guard which closes the given Connection on destruction unless cleared.
|
188
|
+
*/
|
189
|
+
class ConnectionGuard {
|
190
|
+
private:
|
191
|
+
ConnectionPtr connection;
|
192
|
+
bool cleared;
|
193
|
+
|
194
|
+
public:
|
195
|
+
ConnectionGuard(const ConnectionPtr &_connection)
|
196
|
+
: connection(_connection),
|
197
|
+
cleared(false)
|
198
|
+
{ }
|
199
|
+
|
200
|
+
~ConnectionGuard() {
|
201
|
+
if (!cleared) {
|
202
|
+
connection->disconnect();
|
203
|
+
}
|
204
|
+
}
|
205
|
+
|
206
|
+
void clear() {
|
207
|
+
cleared = true;
|
208
|
+
}
|
209
|
+
};
|
210
|
+
|
211
|
+
|
212
|
+
enum ExceptionHandlingMode {
|
213
|
+
PRINT,
|
214
|
+
THROW,
|
215
|
+
IGNORE
|
216
|
+
};
|
217
|
+
|
218
|
+
|
219
|
+
class LoggerFactory;
|
220
|
+
typedef shared_ptr<LoggerFactory> LoggerFactoryPtr;
|
221
|
+
|
222
|
+
inline void _checkinConnection(const LoggerFactoryPtr &loggerFactory, const ConnectionPtr &connection);
|
223
|
+
|
224
|
+
|
225
|
+
class Logger: public boost::noncopyable {
|
226
|
+
private:
|
227
|
+
static const int INT64_STR_BUFSIZE = 22; // Long enough for a 64-bit number.
|
228
|
+
static const unsigned long long IO_TIMEOUT = 5000000; // In microseconds.
|
229
|
+
|
230
|
+
const LoggerFactoryPtr loggerFactory;
|
231
|
+
const ConnectionPtr connection;
|
232
|
+
const string txnId;
|
233
|
+
const string groupName;
|
234
|
+
const string category;
|
235
|
+
const string unionStationKey;
|
236
|
+
const ExceptionHandlingMode exceptionHandlingMode;
|
237
|
+
bool shouldFlushToDiskAfterClose;
|
238
|
+
|
239
|
+
/**
|
240
|
+
* Buffer must be at least txnId.size() + 1 + INT64_STR_BUFSIZE + 1 bytes.
|
241
|
+
*/
|
242
|
+
char *insertTxnIdAndTimestamp(char *buffer, const char *end) {
|
243
|
+
assert(end - buffer >= int(txnId.size() + 1 + INT64_STR_BUFSIZE + 1));
|
244
|
+
int size;
|
245
|
+
|
246
|
+
// "txn-id-here"
|
247
|
+
buffer = appendData(buffer, end, txnId);
|
248
|
+
|
249
|
+
// "txn-id-here "
|
250
|
+
buffer = appendData(buffer, end, " ", 1);
|
251
|
+
|
252
|
+
// "txn-id-here 123456"
|
253
|
+
assert(end - buffer >= INT64_STR_BUFSIZE);
|
254
|
+
size = snprintf(buffer, INT64_STR_BUFSIZE, "%llu", SystemTime::getUsec());
|
255
|
+
if (size >= INT64_STR_BUFSIZE) {
|
256
|
+
// The buffer is too small.
|
257
|
+
throw IOException("Cannot format a new transaction log message timestamp.");
|
258
|
+
}
|
259
|
+
buffer += size;
|
260
|
+
|
261
|
+
// "txn-id-here 123456 "
|
262
|
+
buffer = appendData(buffer, end, " ", 1);
|
263
|
+
|
264
|
+
return buffer;
|
265
|
+
}
|
266
|
+
|
267
|
+
template<typename ExceptionType>
|
268
|
+
void handleException(const ExceptionType &e) {
|
269
|
+
switch (exceptionHandlingMode) {
|
270
|
+
case THROW:
|
271
|
+
throw e;
|
272
|
+
case PRINT:
|
273
|
+
try {
|
274
|
+
const tracable_exception &te =
|
275
|
+
dynamic_cast<const tracable_exception &>(e);
|
276
|
+
P_WARN(te.what() << "\n" << te.backtrace());
|
277
|
+
} catch (const bad_cast &) {
|
278
|
+
P_WARN(e.what());
|
279
|
+
}
|
280
|
+
break;
|
281
|
+
default:
|
282
|
+
break;
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
public:
|
287
|
+
Logger()
|
288
|
+
: exceptionHandlingMode(PRINT)
|
289
|
+
{ }
|
290
|
+
|
291
|
+
Logger(const LoggerFactoryPtr &_loggerFactory,
|
292
|
+
const ConnectionPtr &_connection,
|
293
|
+
const string &_txnId,
|
294
|
+
const string &_groupName,
|
295
|
+
const string &_category,
|
296
|
+
const string &_unionStationKey,
|
297
|
+
ExceptionHandlingMode _exceptionHandlingMode = PRINT)
|
298
|
+
: loggerFactory(_loggerFactory),
|
299
|
+
connection(_connection),
|
300
|
+
txnId(_txnId),
|
301
|
+
groupName(_groupName),
|
302
|
+
category(_category),
|
303
|
+
unionStationKey(_unionStationKey),
|
304
|
+
exceptionHandlingMode(_exceptionHandlingMode),
|
305
|
+
shouldFlushToDiskAfterClose(false)
|
306
|
+
{ }
|
307
|
+
|
308
|
+
~Logger() {
|
309
|
+
TRACE_POINT();
|
310
|
+
if (connection == NULL) {
|
311
|
+
return;
|
312
|
+
}
|
313
|
+
ConnectionLock l(connection);
|
314
|
+
if (!connection->connected()) {
|
315
|
+
return;
|
316
|
+
}
|
317
|
+
|
318
|
+
char timestamp[2 * sizeof(unsigned long long) + 1];
|
319
|
+
integerToHexatri<unsigned long long>(SystemTime::getUsec(),
|
320
|
+
timestamp);
|
321
|
+
|
322
|
+
UPDATE_TRACE_POINT();
|
323
|
+
ConnectionGuard guard(connection);
|
324
|
+
try {
|
325
|
+
unsigned long long timeout = IO_TIMEOUT;
|
326
|
+
writeArrayMessage(connection->fd, &timeout,
|
327
|
+
"closeTransaction",
|
328
|
+
txnId.c_str(),
|
329
|
+
timestamp,
|
330
|
+
NULL);
|
331
|
+
|
332
|
+
if (shouldFlushToDiskAfterClose) {
|
333
|
+
UPDATE_TRACE_POINT();
|
334
|
+
timeout = IO_TIMEOUT;
|
335
|
+
writeArrayMessage(connection->fd, &timeout,
|
336
|
+
"flush", NULL);
|
337
|
+
readArrayMessage(connection->fd, &timeout);
|
338
|
+
}
|
339
|
+
|
340
|
+
_checkinConnection(loggerFactory, connection);
|
341
|
+
guard.clear();
|
342
|
+
} catch (const SystemException &e) {
|
343
|
+
string errorResponse;
|
344
|
+
|
345
|
+
UPDATE_TRACE_POINT();
|
346
|
+
guard.clear();
|
347
|
+
if (connection->disconnect(errorResponse)) {
|
348
|
+
handleException(IOException(
|
349
|
+
"Logging agent disconnected with error: " +
|
350
|
+
errorResponse));
|
351
|
+
} else {
|
352
|
+
handleException(e);
|
353
|
+
}
|
354
|
+
}
|
355
|
+
}
|
356
|
+
|
357
|
+
void message(const StaticString &text) {
|
358
|
+
TRACE_POINT();
|
359
|
+
if (connection == NULL) {
|
360
|
+
P_TRACE(3, "[Union Station log to null] " << text);
|
361
|
+
return;
|
362
|
+
}
|
363
|
+
ConnectionLock l(connection);
|
364
|
+
if (!connection->connected()) {
|
365
|
+
P_TRACE(3, "[Union Station log to null] " << text);
|
366
|
+
return;
|
367
|
+
}
|
368
|
+
|
369
|
+
char timestamp[2 * sizeof(unsigned long long) + 1];
|
370
|
+
integerToHexatri<unsigned long long>(SystemTime::getUsec(), timestamp);
|
371
|
+
|
372
|
+
UPDATE_TRACE_POINT();
|
373
|
+
ConnectionGuard guard(connection);
|
374
|
+
try {
|
375
|
+
unsigned long long timeout = IO_TIMEOUT;
|
376
|
+
P_TRACE(3, "[Union Station log] " << txnId << " " << timestamp << " " << text);
|
377
|
+
writeArrayMessage(connection->fd, &timeout,
|
378
|
+
"log",
|
379
|
+
txnId.c_str(),
|
380
|
+
timestamp,
|
381
|
+
NULL);
|
382
|
+
writeScalarMessage(connection->fd, text, &timeout);
|
383
|
+
guard.clear();
|
384
|
+
} catch (const std::exception &e) {
|
385
|
+
string errorResponse;
|
386
|
+
|
387
|
+
UPDATE_TRACE_POINT();
|
388
|
+
guard.clear();
|
389
|
+
if (connection->disconnect(errorResponse)) {
|
390
|
+
handleException(IOException(
|
391
|
+
"Logging agent disconnected with error: " +
|
392
|
+
errorResponse));
|
393
|
+
} else {
|
394
|
+
handleException(e);
|
395
|
+
}
|
396
|
+
}
|
397
|
+
}
|
398
|
+
|
399
|
+
void abort(const StaticString &text) {
|
400
|
+
message("ABORT");
|
401
|
+
}
|
402
|
+
|
403
|
+
void flushToDiskAfterClose(bool value) {
|
404
|
+
shouldFlushToDiskAfterClose = value;
|
405
|
+
}
|
406
|
+
|
407
|
+
bool isNull() const {
|
408
|
+
return connection == NULL;
|
409
|
+
}
|
410
|
+
|
411
|
+
const string &getTxnId() const {
|
412
|
+
return txnId;
|
413
|
+
}
|
414
|
+
|
415
|
+
const string &getGroupName() const {
|
416
|
+
return groupName;
|
417
|
+
}
|
418
|
+
|
419
|
+
const string &getCategory() const {
|
420
|
+
return category;
|
421
|
+
}
|
422
|
+
|
423
|
+
const string &getUnionStationKey() const {
|
424
|
+
return unionStationKey;
|
425
|
+
}
|
426
|
+
};
|
427
|
+
|
428
|
+
typedef shared_ptr<Logger> LoggerPtr;
|
429
|
+
|
430
|
+
|
431
|
+
class ScopeLog: public noncopyable {
|
432
|
+
private:
|
433
|
+
Logger * const log;
|
434
|
+
enum {
|
435
|
+
NAME,
|
436
|
+
GRANULAR
|
437
|
+
} type;
|
438
|
+
union {
|
439
|
+
const char *name;
|
440
|
+
struct {
|
441
|
+
const char *endMessage;
|
442
|
+
const char *abortMessage;
|
443
|
+
} granular;
|
444
|
+
} data;
|
445
|
+
bool ok;
|
446
|
+
|
447
|
+
static string timevalToString(struct timeval &tv) {
|
448
|
+
unsigned long long i = (unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec;
|
449
|
+
return usecToString(i);
|
450
|
+
}
|
451
|
+
|
452
|
+
static string usecToString(unsigned long long usec) {
|
453
|
+
char timestamp[2 * sizeof(unsigned long long) + 1];
|
454
|
+
integerToHexatri<unsigned long long>(usec, timestamp);
|
455
|
+
return timestamp;
|
456
|
+
}
|
457
|
+
|
458
|
+
public:
|
459
|
+
ScopeLog()
|
460
|
+
: log(NULL)
|
461
|
+
{ }
|
462
|
+
|
463
|
+
ScopeLog(const LoggerPtr &_log, const char *name)
|
464
|
+
: log(_log.get())
|
465
|
+
{
|
466
|
+
type = NAME;
|
467
|
+
data.name = name;
|
468
|
+
ok = false;
|
469
|
+
|
470
|
+
char message[150];
|
471
|
+
char *pos = message;
|
472
|
+
const char *end = message + sizeof(message);
|
473
|
+
struct rusage usage;
|
474
|
+
|
475
|
+
pos = appendData(pos, end, "BEGIN: ");
|
476
|
+
pos = appendData(pos, end, name);
|
477
|
+
pos = appendData(pos, end, " (");
|
478
|
+
pos = appendData(pos, end, usecToString(SystemTime::getUsec()));
|
479
|
+
pos = appendData(pos, end, ",");
|
480
|
+
if (getrusage(RUSAGE_SELF, &usage) == -1) {
|
481
|
+
int e = errno;
|
482
|
+
throw SystemException("getrusage() failed", e);
|
483
|
+
}
|
484
|
+
pos = appendData(pos, end, timevalToString(usage.ru_utime));
|
485
|
+
pos = appendData(pos, end, ",");
|
486
|
+
pos = appendData(pos, end, timevalToString(usage.ru_stime));
|
487
|
+
pos = appendData(pos, end, ") ");
|
488
|
+
|
489
|
+
if (log != NULL) {
|
490
|
+
log->message(StaticString(message, pos - message));
|
491
|
+
}
|
492
|
+
}
|
493
|
+
|
494
|
+
ScopeLog(const LoggerPtr &_log,
|
495
|
+
const char *beginMessage,
|
496
|
+
const char *endMessage,
|
497
|
+
const char *abortMessage = NULL)
|
498
|
+
: log(_log.get())
|
499
|
+
{
|
500
|
+
if (_log != NULL) {
|
501
|
+
type = GRANULAR;
|
502
|
+
data.granular.endMessage = endMessage;
|
503
|
+
data.granular.abortMessage = abortMessage;
|
504
|
+
ok = abortMessage == NULL;
|
505
|
+
_log->message(beginMessage);
|
506
|
+
}
|
507
|
+
}
|
508
|
+
|
509
|
+
~ScopeLog() {
|
510
|
+
if (log == NULL) {
|
511
|
+
return;
|
512
|
+
}
|
513
|
+
if (type == NAME) {
|
514
|
+
char message[150];
|
515
|
+
char *pos = message;
|
516
|
+
const char *end = message + sizeof(message);
|
517
|
+
struct rusage usage;
|
518
|
+
|
519
|
+
if (ok) {
|
520
|
+
pos = appendData(pos, end, "END: ");
|
521
|
+
} else {
|
522
|
+
pos = appendData(pos, end, "FAIL: ");
|
523
|
+
}
|
524
|
+
pos = appendData(pos, end, data.name);
|
525
|
+
pos = appendData(pos, end, " (");
|
526
|
+
pos = appendData(pos, end, usecToString(SystemTime::getUsec()));
|
527
|
+
pos = appendData(pos, end, ",");
|
528
|
+
if (getrusage(RUSAGE_SELF, &usage) == -1) {
|
529
|
+
int e = errno;
|
530
|
+
throw SystemException("getrusage() failed", e);
|
531
|
+
}
|
532
|
+
pos = appendData(pos, end, timevalToString(usage.ru_utime));
|
533
|
+
pos = appendData(pos, end, ",");
|
534
|
+
pos = appendData(pos, end, timevalToString(usage.ru_stime));
|
535
|
+
pos = appendData(pos, end, ")");
|
536
|
+
|
537
|
+
log->message(StaticString(message, pos - message));
|
538
|
+
} else {
|
539
|
+
if (ok) {
|
540
|
+
log->message(data.granular.endMessage);
|
541
|
+
} else {
|
542
|
+
log->message(data.granular.abortMessage);
|
543
|
+
}
|
544
|
+
}
|
545
|
+
}
|
546
|
+
|
547
|
+
void success() {
|
548
|
+
ok = true;
|
549
|
+
}
|
550
|
+
};
|
551
|
+
|
552
|
+
|
553
|
+
class LoggerFactory: public enable_shared_from_this<LoggerFactory> {
|
554
|
+
private:
|
555
|
+
static const unsigned int CONNECTION_POOL_MAX_SIZE = 10;
|
556
|
+
|
557
|
+
const string serverAddress;
|
558
|
+
const string username;
|
559
|
+
const string password;
|
560
|
+
const string nodeName;
|
561
|
+
RandomGenerator randomGenerator;
|
562
|
+
|
563
|
+
LoggerPtr nullLogger;
|
564
|
+
|
565
|
+
/** Lock protecting the fields that follow, but not the
|
566
|
+
* contents of the connection object.
|
567
|
+
*/
|
568
|
+
mutable boost::mutex syncher;
|
569
|
+
vector<ConnectionPtr> connectionPool;
|
570
|
+
unsigned int maxConnectTries;
|
571
|
+
unsigned long long reconnectTimeout;
|
572
|
+
unsigned long long nextReconnectTime;
|
573
|
+
|
574
|
+
static string determineNodeName(const string &givenNodeName) {
|
575
|
+
if (givenNodeName.empty()) {
|
576
|
+
return getHostName();
|
577
|
+
} else {
|
578
|
+
return givenNodeName;
|
579
|
+
}
|
580
|
+
}
|
581
|
+
|
582
|
+
static bool isNetworkError(int code) {
|
583
|
+
return code == EPIPE || code == ECONNREFUSED || code == ECONNRESET
|
584
|
+
|| code == EHOSTUNREACH || code == ENETDOWN || code == ENETUNREACH
|
585
|
+
|| code == ETIMEDOUT;
|
586
|
+
}
|
587
|
+
|
588
|
+
template<typename T>
|
589
|
+
static bool instanceof(const std::exception &e) {
|
590
|
+
try {
|
591
|
+
(void) dynamic_cast<const T &>(e);
|
592
|
+
return true;
|
593
|
+
} catch (const bad_cast &) {
|
594
|
+
return false;
|
595
|
+
}
|
596
|
+
}
|
597
|
+
|
598
|
+
ConnectionPtr createNewConnection() {
|
599
|
+
TRACE_POINT();
|
600
|
+
int fd;
|
601
|
+
vector<string> args;
|
602
|
+
unsigned long long timeout = 15000000;
|
603
|
+
|
604
|
+
fd = connectToServer(serverAddress);
|
605
|
+
FdGuard guard(fd, true);
|
606
|
+
if (!readArrayMessage(fd, args, &timeout)) {
|
607
|
+
throw IOException("The logging agent closed the connection before sending a version identifier.");
|
608
|
+
}
|
609
|
+
if (args.size() != 2 || args[0] != "version") {
|
610
|
+
throw IOException("The logging agent server didn't sent a valid version identifier.");
|
611
|
+
}
|
612
|
+
if (args[1] != "1") {
|
613
|
+
string message = "Unsupported logging agent protocol version " +
|
614
|
+
args[1] + ".";
|
615
|
+
throw IOException(message);
|
616
|
+
}
|
617
|
+
|
618
|
+
UPDATE_TRACE_POINT();
|
619
|
+
writeScalarMessage(fd, username, &timeout);
|
620
|
+
writeScalarMessage(fd, password, &timeout);
|
621
|
+
|
622
|
+
UPDATE_TRACE_POINT();
|
623
|
+
if (!readArrayMessage(fd, args, &timeout)) {
|
624
|
+
throw IOException("The logging agent did not send an authentication response.");
|
625
|
+
} else if (args.size() != 1) {
|
626
|
+
throw IOException("The authentication response that the logging agent sent is not valid.");
|
627
|
+
} else if (args[0] != "ok") {
|
628
|
+
throw SecurityException("The logging agent server denied authentication: " + args[0]);
|
629
|
+
}
|
630
|
+
|
631
|
+
UPDATE_TRACE_POINT();
|
632
|
+
writeArrayMessage(fd, &timeout, "init", nodeName.c_str(), NULL);
|
633
|
+
if (!readArrayMessage(fd, args, &timeout)) {
|
634
|
+
throw SystemException("Cannot connect to logging server", ECONNREFUSED);
|
635
|
+
} else if (args.size() != 1) {
|
636
|
+
throw IOException("Logging server returned an invalid reply for the 'init' command");
|
637
|
+
} else if (args[0] == "server shutting down") {
|
638
|
+
throw SystemException("Cannot connect to server", ECONNREFUSED);
|
639
|
+
} else if (args[0] != "ok") {
|
640
|
+
throw IOException("Logging server returned an invalid reply for the 'init' command");
|
641
|
+
}
|
642
|
+
|
643
|
+
guard.clear();
|
644
|
+
return make_shared<Connection>(fd);
|
645
|
+
}
|
646
|
+
|
647
|
+
public:
|
648
|
+
LoggerFactory() {
|
649
|
+
nullLogger = make_shared<Logger>();
|
650
|
+
}
|
651
|
+
|
652
|
+
LoggerFactory(const string &_serverAddress, const string &_username,
|
653
|
+
const string &_password, const string &_nodeName = string())
|
654
|
+
: serverAddress(_serverAddress),
|
655
|
+
username(_username),
|
656
|
+
password(_password),
|
657
|
+
nodeName(determineNodeName(_nodeName))
|
658
|
+
{
|
659
|
+
nullLogger = make_shared<Logger>();
|
660
|
+
if (!_serverAddress.empty() && isLocalSocketAddress(_serverAddress)) {
|
661
|
+
maxConnectTries = 10;
|
662
|
+
} else {
|
663
|
+
maxConnectTries = 1;
|
664
|
+
}
|
665
|
+
reconnectTimeout = 1000000;
|
666
|
+
nextReconnectTime = 0;
|
667
|
+
}
|
668
|
+
|
669
|
+
ConnectionPtr checkoutConnection() {
|
670
|
+
TRACE_POINT();
|
671
|
+
unique_lock<boost::mutex> l(syncher);
|
672
|
+
if (!connectionPool.empty()) {
|
673
|
+
P_TRACE(3, "Checked out existing connection");
|
674
|
+
ConnectionPtr connection = connectionPool.back();
|
675
|
+
connectionPool.pop_back();
|
676
|
+
return connection;
|
677
|
+
|
678
|
+
} else {
|
679
|
+
if (SystemTime::getUsec() < nextReconnectTime) {
|
680
|
+
P_TRACE(3, "Not yet time to reconnect; returning NULL connection");
|
681
|
+
return ConnectionPtr();
|
682
|
+
}
|
683
|
+
|
684
|
+
l.unlock();
|
685
|
+
P_TRACE(3, "Creating new connection with logging agent");
|
686
|
+
ConnectionPtr connection;
|
687
|
+
try {
|
688
|
+
connection = createNewConnection();
|
689
|
+
} catch (const TimeoutException &) {
|
690
|
+
l.lock();
|
691
|
+
P_WARN("Timeout trying to connect to the logging agent at " << serverAddress << "; " <<
|
692
|
+
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
693
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
694
|
+
return ConnectionPtr();
|
695
|
+
} catch (const tracable_exception &e) {
|
696
|
+
l.lock();
|
697
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
698
|
+
if (instanceof<IOException>(e) || instanceof<SystemException>(e)) {
|
699
|
+
P_WARN("Cannot connect to the logging agent at " << serverAddress <<
|
700
|
+
" (" << e.what() << "); will reconnect in " <<
|
701
|
+
reconnectTimeout / 1000000 << " second(s).");
|
702
|
+
return ConnectionPtr();
|
703
|
+
} else {
|
704
|
+
throw;
|
705
|
+
}
|
706
|
+
}
|
707
|
+
|
708
|
+
return connection;
|
709
|
+
}
|
710
|
+
}
|
711
|
+
|
712
|
+
void checkinConnection(const ConnectionPtr &connection) {
|
713
|
+
lock_guard<boost::mutex> l(syncher);
|
714
|
+
if (connectionPool.size() < CONNECTION_POOL_MAX_SIZE) {
|
715
|
+
connectionPool.push_back(connection);
|
716
|
+
} else {
|
717
|
+
connection->disconnect();
|
718
|
+
}
|
719
|
+
}
|
720
|
+
|
721
|
+
LoggerPtr createNullLogger() const {
|
722
|
+
return nullLogger;
|
723
|
+
}
|
724
|
+
|
725
|
+
LoggerPtr newTransaction(const string &groupName,
|
726
|
+
const string &category = "requests",
|
727
|
+
const string &unionStationKey = string(),
|
728
|
+
const string &filters = string())
|
729
|
+
{
|
730
|
+
if (serverAddress.empty()) {
|
731
|
+
return createNullLogger();
|
732
|
+
}
|
733
|
+
|
734
|
+
unsigned long long timestamp = SystemTime::getUsec();
|
735
|
+
char txnId[
|
736
|
+
2 * sizeof(unsigned int) + // max hex timestamp size
|
737
|
+
11 + // space for a random identifier
|
738
|
+
1 // null terminator
|
739
|
+
];
|
740
|
+
char *end;
|
741
|
+
unsigned int timestampSize;
|
742
|
+
char timestampStr[2 * sizeof(unsigned long long) + 1];
|
743
|
+
|
744
|
+
// "[timestamp]"
|
745
|
+
// Our timestamp is like a Unix timestamp but with minutes
|
746
|
+
// resolution instead of seconds. 32 bits will last us for
|
747
|
+
// about 8000 years.
|
748
|
+
timestampSize = integerToHexatri<unsigned int>(timestamp / 1000000 / 60,
|
749
|
+
txnId);
|
750
|
+
end = txnId + timestampSize;
|
751
|
+
|
752
|
+
// "[timestamp]-"
|
753
|
+
*end = '-';
|
754
|
+
end++;
|
755
|
+
|
756
|
+
// "[timestamp]-[random id]"
|
757
|
+
randomGenerator.generateAsciiString(end, 11);
|
758
|
+
end += 11;
|
759
|
+
*end = '\0';
|
760
|
+
|
761
|
+
integerToHexatri<unsigned long long>(timestamp, timestampStr);
|
762
|
+
|
763
|
+
ConnectionPtr connection = checkoutConnection();
|
764
|
+
if (connection == NULL) {
|
765
|
+
return createNullLogger();
|
766
|
+
}
|
767
|
+
|
768
|
+
ConnectionLock cl(connection);
|
769
|
+
ConnectionGuard guard(connection);
|
770
|
+
|
771
|
+
try {
|
772
|
+
unsigned long long timeout = 15000000;
|
773
|
+
|
774
|
+
writeArrayMessage(connection->fd, &timeout,
|
775
|
+
"openTransaction",
|
776
|
+
txnId,
|
777
|
+
groupName.c_str(),
|
778
|
+
"",
|
779
|
+
category.c_str(),
|
780
|
+
timestampStr,
|
781
|
+
unionStationKey.c_str(),
|
782
|
+
"true",
|
783
|
+
"true",
|
784
|
+
filters.c_str(),
|
785
|
+
NULL);
|
786
|
+
|
787
|
+
vector<string> args;
|
788
|
+
if (!readArrayMessage(connection->fd, args, &timeout)) {
|
789
|
+
lock_guard<boost::mutex> l(syncher);
|
790
|
+
P_WARN("The logging agent at " << serverAddress <<
|
791
|
+
" closed the connection (no error message given);" <<
|
792
|
+
" will reconnect in " << reconnectTimeout / 1000000 <<
|
793
|
+
" second(s).");
|
794
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
795
|
+
return createNullLogger();
|
796
|
+
} else if (args.size() == 2 && args[0] == "error") {
|
797
|
+
lock_guard<boost::mutex> l(syncher);
|
798
|
+
P_WARN("The logging agent at " << serverAddress <<
|
799
|
+
" closed the connection (error message: " << args[1] <<
|
800
|
+
"); will reconnect in " << reconnectTimeout / 1000000 <<
|
801
|
+
" second(s).");
|
802
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
803
|
+
return createNullLogger();
|
804
|
+
} else if (args.empty() || args[0] != "ok") {
|
805
|
+
lock_guard<boost::mutex> l(syncher);
|
806
|
+
P_WARN("The logging agent at " << serverAddress <<
|
807
|
+
" sent an unexpected reply;" <<
|
808
|
+
" will reconnect in " << reconnectTimeout / 1000000 <<
|
809
|
+
" second(s).");
|
810
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
811
|
+
return createNullLogger();
|
812
|
+
}
|
813
|
+
|
814
|
+
guard.clear();
|
815
|
+
return make_shared<Logger>(shared_from_this(),
|
816
|
+
connection,
|
817
|
+
string(txnId, end - txnId),
|
818
|
+
groupName, category,
|
819
|
+
unionStationKey);
|
820
|
+
|
821
|
+
} catch (const TimeoutException &) {
|
822
|
+
lock_guard<boost::mutex> l(syncher);
|
823
|
+
P_WARN("Timeout trying to communicate with the logging agent at " << serverAddress << "; " <<
|
824
|
+
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
825
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
826
|
+
return createNullLogger();
|
827
|
+
|
828
|
+
} catch (const SystemException &e) {
|
829
|
+
if (e.code() == ENOENT || isNetworkError(e.code())) {
|
830
|
+
string errorResponse;
|
831
|
+
bool gotErrorResponse;
|
832
|
+
|
833
|
+
guard.clear();
|
834
|
+
gotErrorResponse = connection->disconnect(errorResponse);
|
835
|
+
lock_guard<boost::mutex> l(syncher);
|
836
|
+
if (gotErrorResponse) {
|
837
|
+
P_WARN("The logging agent at " << serverAddress <<
|
838
|
+
" closed the connection (error message: " << errorResponse <<
|
839
|
+
"); will reconnect in " << reconnectTimeout / 1000000 <<
|
840
|
+
" second(s).");
|
841
|
+
} else {
|
842
|
+
P_WARN("The logging agent at " << serverAddress <<
|
843
|
+
" closed the connection (no error message given);" <<
|
844
|
+
" will reconnect in " << reconnectTimeout / 1000000 <<
|
845
|
+
" second(s).");
|
846
|
+
}
|
847
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
848
|
+
return createNullLogger();
|
849
|
+
} else {
|
850
|
+
throw;
|
851
|
+
}
|
852
|
+
}
|
853
|
+
}
|
854
|
+
|
855
|
+
LoggerPtr continueTransaction(const string &txnId,
|
856
|
+
const string &groupName,
|
857
|
+
const string &category = "requests",
|
858
|
+
const string &unionStationKey = string())
|
859
|
+
{
|
860
|
+
if (serverAddress.empty() || txnId.empty()) {
|
861
|
+
return createNullLogger();
|
862
|
+
}
|
863
|
+
|
864
|
+
char timestampStr[2 * sizeof(unsigned long long) + 1];
|
865
|
+
integerToHexatri<unsigned long long>(SystemTime::getUsec(), timestampStr);
|
866
|
+
|
867
|
+
ConnectionPtr connection = checkoutConnection();
|
868
|
+
if (connection == NULL) {
|
869
|
+
return createNullLogger();
|
870
|
+
}
|
871
|
+
|
872
|
+
ConnectionLock cl(connection);
|
873
|
+
ConnectionGuard guard(connection);
|
874
|
+
|
875
|
+
try {
|
876
|
+
unsigned long long timeout = 15000000;
|
877
|
+
writeArrayMessage(connection->fd, &timeout,
|
878
|
+
"openTransaction",
|
879
|
+
txnId.c_str(),
|
880
|
+
groupName.c_str(),
|
881
|
+
"",
|
882
|
+
category.c_str(),
|
883
|
+
timestampStr,
|
884
|
+
unionStationKey.c_str(),
|
885
|
+
"true",
|
886
|
+
NULL);
|
887
|
+
guard.clear();
|
888
|
+
return make_shared<Logger>(shared_from_this(),
|
889
|
+
connection,
|
890
|
+
txnId, groupName, category,
|
891
|
+
unionStationKey);
|
892
|
+
|
893
|
+
} catch (const TimeoutException &) {
|
894
|
+
lock_guard<boost::mutex> l(syncher);
|
895
|
+
P_WARN("Timeout trying to communicate with the logging agent at " << serverAddress << "; " <<
|
896
|
+
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
897
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
898
|
+
return createNullLogger();
|
899
|
+
|
900
|
+
} catch (const SystemException &e) {
|
901
|
+
if (e.code() == ENOENT || isNetworkError(e.code())) {
|
902
|
+
string errorResponse;
|
903
|
+
bool gotErrorResponse;
|
904
|
+
|
905
|
+
guard.clear();
|
906
|
+
gotErrorResponse = connection->disconnect(errorResponse);
|
907
|
+
lock_guard<boost::mutex> l(syncher);
|
908
|
+
if (gotErrorResponse) {
|
909
|
+
P_WARN("The logging agent at " << serverAddress <<
|
910
|
+
" closed the connection (error message: " << errorResponse <<
|
911
|
+
"); will reconnect in " << reconnectTimeout / 1000000 <<
|
912
|
+
" second(s).");
|
913
|
+
} else {
|
914
|
+
P_WARN("The logging agent at " << serverAddress <<
|
915
|
+
" closed the connection (no error message given);" <<
|
916
|
+
" will reconnect in " << reconnectTimeout / 1000000 <<
|
917
|
+
" second(s).");
|
918
|
+
}
|
919
|
+
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
920
|
+
return createNullLogger();
|
921
|
+
} else {
|
922
|
+
throw;
|
923
|
+
}
|
924
|
+
}
|
925
|
+
}
|
926
|
+
|
927
|
+
void setMaxConnectTries(unsigned int value) {
|
928
|
+
lock_guard<boost::mutex> l(syncher);
|
929
|
+
maxConnectTries = value;
|
930
|
+
}
|
931
|
+
|
932
|
+
void setReconnectTimeout(unsigned long long usec) {
|
933
|
+
lock_guard<boost::mutex> l(syncher);
|
934
|
+
reconnectTimeout = usec;
|
935
|
+
}
|
936
|
+
|
937
|
+
bool isNull() const {
|
938
|
+
return serverAddress.empty();
|
939
|
+
}
|
940
|
+
|
941
|
+
const string &getAddress() const {
|
942
|
+
return serverAddress;
|
943
|
+
}
|
944
|
+
|
945
|
+
const string &getUsername() const {
|
946
|
+
return username;
|
947
|
+
}
|
948
|
+
|
949
|
+
const string &getPassword() const {
|
950
|
+
return password;
|
951
|
+
}
|
952
|
+
|
953
|
+
/**
|
954
|
+
* @post !result.empty()
|
955
|
+
*/
|
956
|
+
const string &getNodeName() const {
|
957
|
+
return nodeName;
|
958
|
+
}
|
959
|
+
};
|
960
|
+
|
961
|
+
|
962
|
+
inline void
|
963
|
+
_checkinConnection(const LoggerFactoryPtr &loggerFactory, const ConnectionPtr &connection) {
|
964
|
+
loggerFactory->checkinConnection(connection);
|
965
|
+
}
|
966
|
+
|
967
|
+
|
968
|
+
} // namespace UnionStation
|
969
|
+
} // namespace Passenger
|
970
|
+
|
971
|
+
#endif /* _PASSENGER_UNION_STATION_H_ */
|
972
|
+
|